Как найти идентификатор окна X под указателем мыши в bash?

20

Из сценария bash есть ли способ получить идентификатор окна X под указателем мыши?

(редактировать) Мне нужно, чтобы процесс не был интерактивным.

Peter.O
источник

Ответы:

25

xdotoolпредоставляет указатель location ( xdotool getmouselocation), и последние версии (начиная с 2.20110530.1) указывают, какое окно также находится в этом месте . Ни одна из xwininfo, wmctrlили более ранние версии не xdotoolимеют возможности сопоставить окно с положением экрана, где оно видно.

Основной вызов библиотеки X - это XQueryPointer(соответствует QueryPointerсообщению). Вот простой скрипт-обертка Python вокруг этого вызова (с использованием ctypes). Проверка ошибок в основном опущена. Предполагается, что вы используете экран 0 (если вы не знали, что на дисплеях может быть более одного экрана, игнорируйте это).

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

Пример использования:

xwininfo -tree -id $(XQueryPointer)
Жиль "ТАК - перестань быть злым"
источник
1
Спасибо, Жиль: Это (почти) именно то, что мне нужно ... Это идеально, но для факта, что он возвращает значение «0» для самого рабочего стола. Возвращается ненулевой идентификатор окна (для рабочего стола) с помощью асинхронного xdotool click 1метода, упомянутого в комментарии к ответу Брюса Эдигера . Ненулевой идентификатор рабочего стола действителен, так как он возвращает соответствующее изображение через import -window $nonzeroID screen.png.... Есть ли какая-то простая настройка для скрипта Python, возвращающая это значение для рабочего стола ?
Peter.O
@Gilles ... Тестирование $(XQueryPointer)на 0, и вызов xwininfo -rootдля этого условия устраняющего этой причуды .. Спасибо ..
Peter.O
@fred Не проверено, потому что я не перед машиной Unix: попробуйте распечатать, root_id.valueесли child_id.value == 0.
Жиль "ТАК - перестань быть злым"
Да, ваш мод работает нормально .. 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))
Ф. Хаури
21

Команда xwininfoвыводит этот вид, но вам нужно щелкнуть в окне, о котором вы хотите получить информацию:

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

xwininfo: Window id: 0xa0000d "flask"

...

Таким образом: xwininfo | grep 'Window id:'может дать вам то, что вы можете разобрать ID из.

Брюс Эдигер
источник
1
Мне нужно, чтобы он был неинтерактивным ...
Peter.O
1
Его можно сделать неинтерактивным, запустив его в фоновом режиме xwinfo |grep window id:' &и следуя за ним xdotool click 1... но это создает риск выполнения переднего плана clickперед тем, как xdotoolсхватить мышь. Я бы даже не использовал номинальное `sleep n, поэтому, хотя этот ответ на ходу, я подожду пока, чтобы увидеть, не появится ли что-нибудь более встроенное ...
Peter.O
8

попробуйте это, он использует только xdotool, но его версия по крайней мере "2.20110530.1"

xdotool getmouselocation --shell | grep WINDOW

чтобы получить идентификатор окна напрямую, вы можете использовать это:

sedGetValue='s/.*=\(.*\)/\1/'
windowId=`xdotool getmouselocation --shell 2>/dev/null |grep WINDOW |sed "$sedGetValue"`
echo $windowId
Водолей Сила
источник
1
сработало, спасибо, кстати, это может быть полезноxdotool getmouselocation --shell | grep WINDOW | awk -F "=" '{print $2}'
user41209
1

xdotool достаточно хорош для этого.

Запустите, xdotool getactivewindowи вы увидите результат (int) Окно может быть над любым монитором. Просто прочитайте, где находится указатель x11, ожидающий щелчка :), и неважно, удаленное ли это окно, vncserver или 3-й рабочий стол в среде рабочего стола куба. Просто работает.

Вы можете играть в нее, используя сон для лучшего тестирования sleep 3; xdotool click 1+2; xdotool getactivewindow.

Я вижу, что getwindowsfocusвозвращает то же значение, чем getactivewindow.

Если вы сделаете щелчки вручную, вы увидите контекстное меню, но щелчок 1 + 2 запускает оба щелчка одновременно, щелкая текущее местоположение мыши и получая нужный идентификатор.

Попытайся :)

m3nda
источник
1
Это дает идентификатор активного окна (где бы оно ни находилось ) независимо от того, находится ли это активное окно под указателем мыши. Согласно формулировке вопроса: «... найдите идентификатор окна X под указателем мыши ...» (где бы эта мышь не находилась).
Peter.O
1
Спасибо за исправление, ты прав. Обновлено . Я смешивал концепцию getmouselocation с activewindow, но в любом случае xdotool достаточно крутой.
m3nda
1

Если у вас есть доступ к python-xlib , вот более короткий и более питонический эквивалент ответа Жиля:

from Xlib.display import Display

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

print(result.child.id)
Ноэ Мартинес
источник
0

Я поиграл с ответом от Питера. И придумал:

xdotool click 1|xwininfo|grep 'Window id:'
Икем Крюгер
источник
1
Это посылает щелчок мыши, поэтому он будет, например, нажимать кнопку, где находится курсор мыши. Это случайно сообщило бы окно, в котором находится курсор, если вы используете клик для фокусировки, но отправка события щелчка разрушительна.
Жиль "ТАК - перестань быть злым"
0

ArchWiki имеет хороший ответ на это:

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

Используя его, sedвы можете сделать это в одной строке, что, вероятно, является наиболее читабельным способом сделать это:

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

Обратите внимание, что xdotoolотсутствовал в моем Debian минимальный X11, в то время как xpropбыл включен (также sedконечно).

Если вы не хотите , чтобы раскошелиться , sedни grepвы можете сделать преобразование текста его целиком bash, что , возможно , является немного более безопасным в случае выходом из xpropизменений немного:

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

Во всяком случае, это все еще странный способ архивировать такую ​​простую задачу.

Tino
источник
3
Это дает идентификатор активного окна вместо окна под указателем мыши.
Peter.O
@ Peter.O Вы правы, это возвращает активное окно. Извините за неправильный ответ, однако с моими тестами это сработало - вероятно, потому что у меня была фокус-следует-мышь.
Тино
0
xprop -root 2>/dev/null | sed -n '/^_NET_ACTIVE_WINDOW/ s/.* // p'
blueyed
источник
1
Это дает идентификатор активного окна вместо окна под указателем мыши.
Peter.O
О, я предполагал неаккуратный фокус (фокус следует за мышью) здесь.
синеватый
@blueyed Focus находится на активных окнах, и эти окна реагируют на KEYBOARD. За мышью следит / отслеживает X11, поскольку он является сервером от него, и когда вы щелкаете по окну, x11 устанавливает фокус оконного менеджера на нажатые окна. Фокус не следует за мышью на самом деле. Вы можете проверить бег xdotool getwindowsfocusиз консоли и перемещение мыши. Значение будет одинаковым до тех пор, пока вы не нажмете кнопку мыши или не будете взаимодействовать с клавиатурой (alt + tab и т. Д.)
m3nda