Jak znaleźć identyfikator okna X pod wskaźnikiem myszy w bash?

20

Czy ze skryptu bash można uzyskać identyfikator okna X pod wskaźnikiem myszy?

(edytuj) Potrzebuję, aby proces był nieinteraktywny.

Peter.O
źródło

Odpowiedzi:

25

xdotoolujawnia położenie wskaźnika ( xdotool getmouselocation), a najnowsze wersje (od 2.20110530.1) wskazują również, które okno znajduje się w tym miejscu . Żaden z xwininfo, wmctrllub starsze wersje xdotoolwydają się mieć sposób, aby dopasować okno przez położenia ekranu, gdzie jest widoczny.

Podstawowym wywołaniem biblioteki X jest XQueryPointer(odpowiadające QueryPointerwiadomości). Oto prosty skrypt otoki Pythona wokół tego wywołania (za pomocą ctypes). Sprawdzanie błędów w dużej mierze zostało pominięte. Załóżmy, że używasz ekranu 0 (jeśli nie wiedziałeś, że wyświetlacze mogą mieć więcej niż jeden ekran, zignoruj ​​to).

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

Przykład użycia:

xwininfo -tree -id $(XQueryPointer)
Gilles „SO- przestań być zły”
źródło
1
Dzięki Gilles: To jest (prawie) dokładnie to, czego potrzebuję ... Jest idealny, ale zwraca wartość 0 dla samego pulpitu. Zwracany jest niezerowy identyfikator okna (dla pulpitu) za pomocą xdotool click 1metody asynchronicznej wymienionej w komentarzu do odpowiedzi Bruce'a Edigera . Niezerowy identyfikator pulpitu jest prawidłowy, ponieważ zwraca odpowiedni obraz za pośrednictwem import -window $nonzeroID screen.png... Czy istnieje jakiś prosty sposób na poprawienie skryptu python, aby zwracał wartość na pulpicie ?
Peter.O,
@Gilles ... Testowanie $(XQueryPointer)dla 0i nazywanie xwininfo -roottego warunku rozwiązuje ten dziwactwo .. Dzięki ..
Peter.O
@ fred Untested, ponieważ nie jestem przed komputerem z systemem uniksowym: spróbuj wydrukować root_id.valueif child_id.value == 0.
Gilles „SO- przestań być zły”
Tak, twój mod działa dobrze .. 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
21

xwininfoKomenda daje tego rodzaju produkcji, ale trzeba kliknąć na okno, które ma informacji na temat:

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

xwininfo: Window id: 0xa0000d "flask"

...

Więc robienie: xwininfo | grep 'Window id:'może dać ci coś, z czego możesz przeanalizować identyfikator.

Bruce Ediger
źródło
1
Potrzebuję, aby był nieinteraktywny ...
Peter.O,
1
Można go uczynić nieinteraktywnym, uruchamiając go w tle xwinfo |grep window id:' &i podążając za nim xdotool click 1... ale to ryzykuje, że pierwszy plan clickwykona się zanim xdotoolzłapie mysz. Nie używałbym nominalnego `snu n, więc chociaż ta odpowiedź jest na dobrej drodze, poczekam chwilę, aby zobaczyć, czy pojawi się coś bardziej wbudowanego ...
Peter.O
8

spróbuj tego, używa tylko xdotool, ale jego wersja to co najmniej „2.20110530.1”

xdotool getmouselocation --shell | grep WINDOW

aby uzyskać identyfikator okna bezpośrednio, możesz użyć tego:

sedGetValue='s/.*=\(.*\)/\1/'
windowId=`xdotool getmouselocation --shell 2>/dev/null |grep WINDOW |sed "$sedGetValue"`
echo $windowId
Wodnik Moc
źródło
1
działało, dzięki, BTW to może się przydaćxdotool getmouselocation --shell | grep WINDOW | awk -F "=" '{print $2}'
user41209
1

xdotool jest wystarczająco dobry, aby to zrobić.

Uruchom, xdotool getactivewindowa zobaczysz wynik (int) Okno może znajdować się na DOWOLNYM monitorze. Po prostu przeczytaj, gdzie znajduje się wskaźnik x11, który czeka na kliknięcie :) i bez względu na to, czy jest to zdalne okno, serwer vncserver czy trzeci pulpit środowiska pulpitu kostki. Po prostu działa.

Możesz grać w tryb uśpienia dla lepszego testowania sleep 3; xdotool click 1+2; xdotool getactivewindow.

Widzę, że getwindowsfocuszwraca tę samą wartość, co getactivewindow.

Jeśli wykonujesz kliknięcia ręcznie, zobaczysz menu kontekstowe, ale kliknięcie 1 + 2 uruchamia oba kliknięcia jednocześnie, klikając bieżącą lokalizację myszy i uzyskując pożądany identyfikator.

Spróbuj :)

m3nda
źródło
1
Daje to identyfikator aktywnego okna (gdziekolwiek to okno może być), niezależnie od tego, czy to aktywne okno znajduje się pod wskaźnikiem myszy. Zgodnie z brzmieniem pytania: „... znajdź identyfikator X okna pod wskaźnikiem myszy ...” (gdziekolwiek ta mysz może być).
Peter.O,
1
Dziękuję za poprawkę, masz rację. Aktualizowany . Mieszałem koncepcję getmouselocation z activewindow, ale w każdym razie xdotool jest wystarczająco fajny.
m3nda
1

Jeśli masz dostęp do python-xlib , oto krótszy i bardziej pythoniczny odpowiednik odpowiedzi Gillesa:

from Xlib.display import Display

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

print(result.child.id)
Noé Martínez
źródło
0

Bawiłem się z odpowiedzią od Peter.O i wymyśliłem:

xdotool click 1|xwininfo|grep 'Window id:'
Ikem Krueger
źródło
1
To powoduje kliknięcie myszą, więc np. Kliknięcie przycisku w miejscu kursora myszy. Nawiasem mówiąc, zgłosi okno, w którym znajduje się kursor, jeśli użyjesz kliknięcia, aby ustawić fokus, ale wysłanie zdarzenia kliknięcia jest zakłócające.
Gilles „SO- przestań być zły”
0

ArchWiki ma dobrą odpowiedź na to:

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

Za pomocą tego sedmożesz to zrobić w jednym wierszu, co jest prawdopodobnie najbardziej czytelnym sposobem:

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

Zauważ, że xdotoolbrakowało go w moim minimalnym X11 Debiana, gdy xpropzostał on dołączony (podobnie sedoczywiście).

Jeśli nie chcesz rozwidlać sedani grepnie możesz całkowicie przekształcić tekstu bash, co może być nieco bezpieczniejsze w przypadku, gdy wynik xpropzmian jest nieco większy :

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

W każdym razie jest to dziwny sposób na zarchiwizowanie tak prostego zadania.

Tino
źródło
3
Daje to identyfikator aktywnego okna zamiast okna pod wskaźnikiem myszy.
Peter.O,
@ Peter.O Masz rację, to zwraca aktywne okno. Przepraszam za złą odpowiedź, jednak z moimi testami zadziałało - prawdopodobnie dlatego, że miałem na sobie funkcję „podążaj za myszą”.
Tino
0
xprop -root 2>/dev/null | sed -n '/^_NET_ACTIVE_WINDOW/ s/.* // p'
niebieskawy
źródło
1
Daje to identyfikator aktywnego okna zamiast okna pod wskaźnikiem myszy.
Peter.O
Och, zakładałem tu niechlujne fokus (fokus podąża za myszą) tutaj.
blueyed
@blueyed Fokus znajduje się na aktywnych oknach i to okno nie reaguje na KLAWIATURĘ. Mysz jest śledzona / śledzona przez X11, ponieważ jest od niej serwerem, a kiedy klikniesz okno, x11 ustawia fokus menedżera okien na kliknięte okna. Ostrość nie podąża za myszą. Możesz sprawdzić uruchamianie xdotool getwindowsfocusz konsoli i poruszanie myszą. Wartość byłaby taka sama, dopóki nie klikniesz myszy lub nie wejdziesz w interakcję z klawiaturą (alt + tab itp.)
m3nda