Como localizo o ID da janela X sob o ponteiro do mouse no bash?

20

Em um script bash, existe alguma maneira de obter o ID da janela X sob o ponteiro do mouse?

(editar) Preciso que o processo seja não interativo.

Peter.O
fonte

Respostas:

25

xdotoolexpõe o local do ponteiro ( xdotool getmouselocation) e versões recentes (desde 2.20110530.1) indicam qual janela também está nesse local . Nada xwininfo, wmctrlou versões mais antigas do xdotoolparecem ter uma maneira de combinar uma janela por uma posição da tela onde é visível.

A chamada da biblioteca X subjacente é XQueryPointer(correspondente a uma QueryPointermensagem). Aqui está um script simples do wrapper Python em torno dessa chamada (usando ctypes). A verificação de erros foi omitida em grande parte. Supõe que você esteja usando a tela 0 (se você não sabia que os monitores poderiam ter mais de uma tela, ignore).

#! /usr/bin/env python
import sys
from ctypes import *
Xlib = CDLL("libX11.so.6")
display = Xlib.XOpenDisplay(None)
if display == 0: sys.exit(2)
w = Xlib.XRootWindow(display, c_int(0))
(root_id, child_id) = (c_uint32(), c_uint32())
(root_x, root_y, win_x, win_y) = (c_int(), c_int(), c_int(), c_int())
mask = c_uint()
ret = Xlib.XQueryPointer(display, c_uint32(w), byref(root_id), byref(child_id),
                         byref(root_x), byref(root_y),
                         byref(win_x), byref(win_y), byref(mask))
if ret == 0: sys.exit(1)
print child_id.value

Exemplo de uso:

xwininfo -tree -id $(XQueryPointer)
Gilles 'SO- parar de ser mau'
fonte
11
Obrigado Gilles: Isso é (quase) exatamente o que eu preciso ... É ideal, mas pelo fato de retornar um valor de '0' para a própria área de trabalho. Um ID de janela diferente de zero é retornado (para a área de trabalho) pelo xdotool click 1método assíncrono mencionado no comentário à resposta de Bruce Ediger . O ID da área de trabalho diferente de zero é válido, pois retorna a imagem apropriada via import -window $nonzeroID screen.png.... Existe algum ajuste simples para o script python retornar esse valor para a área de trabalho ?
Peter.O
@Gilles ... Teste $(XQueryPointer)para 0, e chamando xwininfo -rootpara esta condição resolve esse capricho .. Obrigado ..
Peter.O
@fred Não testado porque não estou na frente de uma máquina unix: tente imprimir root_id.valuese child_id.value == 0.
Gilles 'SO- stop be evil'
Sim, o seu mod fina funciona .. if child_id.value == 0: print root_id.value else: print child_id.value :)
Peter.O
sed /x[0-9]\\++/q\;d <(xwininfo -tree -id $(XQueryPointer))
F. Hauri 14/02
21

O xwininfocomando fornece esse tipo de saída, mas você precisa clicar na janela em que deseja obter informações:

% xwininfo
xwininfo: Please select the window about which you
          would like information by clicking the
          mouse in that window.

xwininfo: Window id: 0xa0000d "flask"

...

Assim: xwininfo | grep 'Window id:'pode dar a você algo do qual você pode analisar o ID.

Bruce Ediger
fonte
11
Eu preciso que ele seja não-interativo ...
Peter.O
11
Isso pode ser feito para não ser interativo, executando-o em segundo plano xwinfo |grep window id:' &e seguindo-o até xdotool click 1... mas isso corre o risco de o primeiro plano ser clickexecutado antes de xdotoolagarrar o mouse. I Rathen não usaria um `sono nominal n, por isso, embora esta resposta é na pista, eu vou esperar um wihile para ver se algo mais em linha transforma-se ...
Peter.O
8

tente isso, ele usa apenas xdotool, mas sua versão é pelo menos "2.20110530.1"

xdotool getmouselocation --shell | grep WINDOW

para obter o ID da janela diretamente, você pode usar isso:

sedGetValue='s/.*=\(.*\)/\1/'
windowId=`xdotool getmouselocation --shell 2>/dev/null |grep WINDOW |sed "$sedGetValue"`
echo $windowId
Poder do Aquário
fonte
11
funcionou, obrigado, BTW isso pode ser útilxdotool getmouselocation --shell | grep WINDOW | awk -F "=" '{print $2}'
user41209 24/03
1

O xdotool é bom o suficiente para fazê-lo.

Execute xdotool getactivewindowe você verá o resultado (int) A janela pode estar em QUALQUER monitor. Basta ler onde está localizado o ponteiro x11 aguardando um clique :) e não importa se é uma janela remota, um servidor vncserver ou a terceira área de trabalho do ambiente de área de trabalho do cubo. Apenas funciona.

Você pode reproduzi-lo usando o sono para obter melhores testes sleep 3; xdotool click 1+2; xdotool getactivewindow.

Eu vi que getwindowsfocusretorna o mesmo valor que getactivewindow.

Se você clicar manualmente, verá o menu contextual, mas clique em 1 + 2 para acionar os dois cliques ao mesmo tempo, clicando no local atual do mouse e obtendo o ID desejado.

Tente :)

m3nda
fonte
11
Isso fornece o ID da janela ativa (onde quer que essa janela esteja), independentemente de essa janela ativa estar ou não sob o ponteiro do mouse. Conforme a redação da pergunta: "... encontre o ID da janela X sob o ponteiro do mouse ..." (onde quer que esse mouse esteja).
Peter.O
11
Obrigado pela correção, você está certo. Atualizado . Eu estava misturando o conceito de getmouselocation com a janela ativa, mas, de qualquer forma, o xdotool é legal o suficiente.
M3nda 25/05
1

Se você tem acesso ao python-xlib , aqui está um equivalente mais curto e mais pitônico da resposta de Gilles:

from Xlib.display import Display

display = Display()
window = display.screen().root
result = window.query_pointer()

print(result.child.id)
Noé Martínez
fonte
0

Eu brinquei com a resposta de Peter.O e descobri:

xdotool click 1|xwininfo|grep 'Window id:'
Ikem Krueger
fonte
11
Isso envia um clique do mouse, portanto, por exemplo, clique em um botão onde está o cursor do mouse. Incidentalmente, ele reportaria a janela em que o cursor está, se você usar o clique para focar, mas o envio de um evento de clique é perturbador.
Gilles 'SO- stop be evil'
0

O ArchWiki tem uma boa resposta para isso:

activeWinLine=$(xprop -root | grep "_NET_ACTIVE_WINDOW(WINDOW)")
activeWinId=${activeWinLine:40}

Usando sedvocê pode fazer isso em uma única linha, que é provavelmente a maneira mais legível de fazer isso:

activeWin="$(xprop -root | sed -n 's/^_NET_ACTIVE_WINDOW(WINDOW): window id # //p')"

Note que xdotoolestava faltando no meu Debian X11 mínimo enquanto xpropestava incluído (da mesma forma é sedclaro).

Se você não deseja bifurcar sednem greppode fazer a transformação do texto inteiramente bash, o que talvez seja um pouco mais seguro, caso a saída das xpropalterações mude um pouco:

activeWin="$(xprop -root)"
activeWin="${activeWin#*_NET_ACTIVE_WINDOW(WINDOW):}'
activeWin="${activeWin%%?_NET_*}'
activeWin="${activeWin##* }'

De qualquer forma, ainda é uma maneira estranha de arquivar uma tarefa tão simples.

Tino
fonte
3
Isso fornece o ID da janela ativa em vez da janela sob o ponteiro do mouse.
Peter.O
@ Peter.O Você está certo, isso retorna a janela ativa. Desculpe a resposta errada, no entanto, com meus testes funcionou - provavelmente porque eu tinha o foco segue o mouse.
Tino
0
xprop -root 2>/dev/null | sed -n '/^_NET_ACTIVE_WINDOW/ s/.* // p'
azulado
fonte
11
Isso fornece o ID da janela ativa em vez da janela sob o ponteiro do mouse.
Peter.O
Ah, eu estava assumindo foco superficial (o foco segue o mouse) aqui.
blueyed
O @blueyed Focus está nas janelas ativas e essas janelas respondem ao TECLADO. O mouse é seguido / rastreado pelo X11 como servidor, e quando você clica em uma janela, o x11 define o foco do gerenciador de janelas como janelas clicadas. O foco não segue o mouse realmente. Você pode verificar a execução xdotool getwindowsfocusem um console e mover o mouse. Valor seria o mesmo até que você clique de mouse ou teclado interagem (alt + tab, etc)
m3nda