Bagaimana cara menemukan ID jendela X di bawah penunjuk tetikus di bash?

20

Dari skrip bash, apakah ada cara untuk mendapatkan ID dari jendela X di bawah penunjuk tetikus?

(sunting) Saya perlu prosesnya menjadi non-interaktif.

Peter.O
sumber

Jawaban:

25

xdotoolmemperlihatkan lokasi penunjuk ( xdotool getmouselocation), dan versi terbaru (sejak 2.20110530.1) menunjukkan jendela mana yang berada di lokasi itu juga . Tak satu pun dari xwininfo, wmctrlatau versi yang lebih lama dari xdotooltampaknya memiliki cara untuk mencocokkan jendela dengan posisi layar di mana itu terlihat.

Panggilan pustaka X yang mendasarinya adalah XQueryPointer(terkait dengan QueryPointerpesan). Berikut ini skrip pembungkus Python sederhana untuk panggilan ini (menggunakan ctypes). Pemeriksaan kesalahan sebagian besar dihilangkan. Asumsikan Anda menggunakan layar 0 (jika Anda tidak tahu bahwa tampilan bisa memiliki lebih dari satu layar, abaikan ini).

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

Contoh penggunaan:

xwininfo -tree -id $(XQueryPointer)
Gilles 'SANGAT berhenti menjadi jahat'
sumber
1
Terima kasih Gilles: Ini (hampir) persis apa yang saya butuhkan ... Ini sangat ideal tetapi untuk kenyataan bahwa ia mengembalikan nilai '0' untuk desktop itu sendiri .. Window ID yang tidak nol dikembalikan (untuk desktop) dengan asynchronous xdotool click 1metode yang disebutkan dalam komentar untuk Bruce Ediger ini jawabannya .. The-nol non ID desktop sedemikian rupa berlaku karena mengembalikan gambar yang sesuai melalui import -window $nonzeroID screen.png.... Apakah ada beberapa Tweak sederhana untuk script python untuk kembali bahwa nilai untuk desktop ?
Peter.O
@Gilles ... Pengujian $(XQueryPointer)untuk 0, dan menyerukan xwininfo -rootuntuk kondisi ini menyelesaikan permainan kata-kata ini .. Terima kasih ..
Peter.O
@ Fred Tidak teruji karena saya tidak di depan mesin unix: coba cetak root_id.valuejika child_id.value == 0.
Gilles 'SO- stop being evil'
Ya, mod Anda berfungsi dengan baik .. 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

The xwininfoperintah memberikan semacam ini output, tetapi Anda harus mengklik pada jendela Anda ingin info tentang:

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

xwininfo: Window id: 0xa0000d "flask"

...

Melakukan hal itu: xwininfo | grep 'Window id:'mungkin memberi Anda sesuatu yang bisa Anda uraikan dari ID.

Bruce Ediger
sumber
1
Saya membutuhkannya untuk tidak interaktif ...
Peter.O
1
Itu bisa dibuat menjadi non-interaktif dengan menjalankannya di latar belakang xwinfo |grep window id:' &, dan mengikutinya dengan xdotool click 1... tapi itu berisiko clickmengeksekusi foreground sebelum xdotoolmeraih mouse. Saya tidak akan menggunakan nominal `sleep n, jadi meskipun jawaban ini tepat, saya akan menunggu sebentar untuk melihat apakah sesuatu yang lebih inline muncul ...
Peter.O
8

coba ini, ini hanya menggunakan xdotool, tetapi versinya paling tidak "2.20110530.1"

xdotool getmouselocation --shell | grep WINDOW

untuk mendapatkan id jendela secara langsung, Anda dapat menggunakan ini:

sedGetValue='s/.*=\(.*\)/\1/'
windowId=`xdotool getmouselocation --shell 2>/dev/null |grep WINDOW |sed "$sedGetValue"`
echo $windowId
Kekuatan Aquarius
sumber
1
berhasil, terima kasih, BTW ini mungkin bergunaxdotool getmouselocation --shell | grep WINDOW | awk -F "=" '{print $2}'
user41209
1

xdotool cukup baik untuk melakukannya.

Jalankan xdotool getactivewindowdan Anda akan melihat hasilnya (int) Jendela bisa melalui monitor APAPUN. Cukup baca di mana letak pointer x11 menunggu klik :), dan tidak masalah apakah itu jendela jarak jauh, vncserver, atau desktop ke-3 dari lingkungan desktop kubus. Hanya bekerja.

Anda dapat memainkannya menggunakan sleep untuk pengujian yang lebih baik sleep 3; xdotool click 1+2; xdotool getactivewindow.

Saya telah melihat bahwa getwindowsfocusmengembalikan nilai yang sama daripada getactivewindow.

Jika Anda melakukan klik secara manual Anda akan melihat menu kontekstual, tetapi klik 1 + 2 menembakkan kedua klik pada saat mengklik pada lokasi mouse saat ini dan mendapatkan id yang diinginkan.

Cobalah :)

m3nda
sumber
1
Ini memberikan ID dari jendela aktif (di mana pun jendela itu mungkin), terlepas dari apakah jendela aktif itu di bawah penunjuk mouse. Sesuai dengan kata-kata dari pertanyaan: "... temukan X window ID di bawah penunjuk mouse ..." (di mana pun mouse itu berada).
Peter.O
1
Terima kasih atas koreksi, benar. Diperbarui . Saya sedang mencampur konsep getmouselocation dengan activewindow, tapi toh, xdotool cukup keren.
m3nda
1

Jika Anda memiliki akses ke python-xlib , berikut ini persamaan yang lebih pendek dan lebih pythonic dengan jawaban Gilles:

from Xlib.display import Display

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

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

Saya bermain-main dengan jawaban dari Peter.O dan muncul dengan:

xdotool click 1|xwininfo|grep 'Window id:'
Ikem Krueger
sumber
1
Itu mengirimkan klik mouse, jadi misalnya akan mengklik tombol di mana kursor mouse berada. Secara tidak sengaja akan melaporkan jendela tempat kursor berada jika Anda menggunakan klik untuk fokus, tetapi mengirimkan peristiwa klik mengganggu.
Gilles 'SANGAT berhenti menjadi jahat'
0

ArchWiki memiliki jawaban yang bagus untuk ini:

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

Menggunakan sed Anda dapat melakukan ini dalam satu baris, yang mungkin merupakan cara yang paling mudah dibaca untuk melakukannya:

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

Catat itu xdotool hilang di Debian minimal X11 saya saat xpropdimasukkan (juga sedtentu saja).

Jika Anda tidak ingin melakukan fork, Anda sedjuga tidak grepdapat melakukan transformasi teks seluruhnya bash, yang mungkin sedikit lebih aman jika output darixprop perubahan sedikit:

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

Bagaimanapun, ini masih merupakan cara aneh untuk mengarsipkan tugas yang begitu sederhana.

Tino
sumber
3
Ini memberikan ID dari jendela yang aktif, bukan jendela di bawah penunjuk mouse.
Peter.O
@ Peter.O Anda benar ini mengembalikan jendela aktif. Maaf untuk jawaban yang salah, namun dengan tes saya itu berhasil - mungkin karena saya telah fokus-mengikuti-mouse.
Tino
0
xprop -root 2>/dev/null | sed -n '/^_NET_ACTIVE_WINDOW/ s/.* // p'
kebiru-biruan
sumber
1
Ini memberikan ID dari jendela yang aktif, bukan jendela di bawah penunjuk mouse.
Peter.O
Oh, saya mengasumsikan fokus ceroboh (fokus mengikuti mouse) di sini.
blueyed
@blueyed Focus ada di jendela aktif, dan jendela ini merespons KEYBOARD. Mouse diikuti / dilacak oleh X11 sebagai server dari itu, dan ketika Anda mengklik windows, x11 menetapkan fokus window-manager ke windows yang diklik. Fokus tidak benar-benar mengikuti mouse. Anda dapat memeriksa berlari xdotool getwindowsfocusdari konsol dan menggerakkan mouse. Nilai akan sama sampai Anda mengklik mouse atau berinteraksi keyboard (alt + tab, dll)
m3nda