Comment trouver l'ID de la fenêtre X sous le pointeur de la souris dans bash?

20

À partir d'un script bash, existe-t-il un moyen d'obtenir l'ID de la fenêtre X sous le pointeur de la souris?

(modifier) ​​J'ai besoin que le processus ne soit pas interactif.

Peter.O
la source

Réponses:

25

xdotoolexpose l'emplacement du pointeur ( xdotool getmouselocation), et les versions récentes (depuis 2.20110530.1) indiquent également quelle fenêtre se trouve à cet emplacement . Aucun des xwininfo, wmctrlou les anciennes versions de xdotoolsemblent avoir un moyen de faire correspondre une fenêtre par une position de l' écran où il est visible.

L'appel de bibliothèque X sous-jacent est XQueryPointer(correspondant à un QueryPointermessage). Voici un simple script d'encapsulation Python autour de cet appel (en utilisant ctypes). Vérification d'erreur largement omise. Suppose que vous utilisez l'écran 0 (si vous ne saviez pas que les écrans peuvent avoir plusieurs écrans, ignorez-le).

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

Exemple d'utilisation:

xwininfo -tree -id $(XQueryPointer)
Gilles 'SO- arrête d'être méchant'
la source
1
Merci Gilles: C'est (presque) exactement ce dont j'ai besoin ... C'est idéal mais pour le fait qu'il retourne une valeur de '0' pour le bureau lui-même .. Un ID de fenêtre non nul est retourné (pour le bureau) par la xdotool click 1méthode asynchrone mentionnée dans le commentaire à la réponse de Bruce Ediger .. L'ID de bureau différent de zéro est valide dans la mesure où il renvoie l'image appropriée via import -window $nonzeroID screen.png.... Y a-t-il un simple ajustement pour que le script python renvoie cette valeur pour le bureau ?
Peter.O
@Gilles ... essai $(XQueryPointer)pour 0, et appelant xwininfo -rootà cette résorbe cette bizarrerie .. Merci ..
Peter.O
@fred Non testé car je ne suis pas devant une machine Unix: essayez d'imprimer root_id.valuesi child_id.value == 0.
Gilles 'SO- arrête d'être méchant'
Oui, votre mod fonctionne bien .. 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

La xwininfocommande donne ce type de sortie, mais vous devez cliquer sur la fenêtre sur laquelle vous souhaitez obtenir des informations:

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

xwininfo: Window id: 0xa0000d "flask"

...

Ce faisant: xwininfo | grep 'Window id:'pourrait vous donner quelque chose dont vous pouvez analyser l'ID.

Bruce Ediger
la source
1
J'ai besoin que ce soit non interactif ...
Peter.O
1
Il peut être rendu non interactif en l'exécutant en arrière-plan xwinfo |grep window id:' &et en le suivant par xdotool click 1... mais cela court le risque que le premier plan clicks'exécute avant de xdotoolsaisir la souris. Je préfère ne pas utiliser un sommeil nominal n, donc bien que cette réponse soit sur la bonne voie, j'attendrai un peu pour voir si quelque chose de plus en ligne apparaît ...
Peter.O
8

essayez ceci, il utilise uniquement xdotool, mais sa version est au moins "2.20110530.1"

xdotool getmouselocation --shell | grep WINDOW

pour obtenir l'id de la fenêtre directement, vous pouvez utiliser ceci:

sedGetValue='s/.*=\(.*\)/\1/'
windowId=`xdotool getmouselocation --shell 2>/dev/null |grep WINDOW |sed "$sedGetValue"`
echo $windowId
Puissance du Verseau
la source
1
travaillé, merci, BTW cela peut être utilexdotool getmouselocation --shell | grep WINDOW | awk -F "=" '{print $2}'
user41209
1

xdotool est assez bon pour le faire.

Courir xdotool getactivewindow et vous verrez le résultat (int) La fenêtre peut être sur N'IMPORTE QUEL moniteur. Il suffit de lire où se trouve le pointeur x11 en attente d'un clic :), et peu importe qu'il s'agisse d'une fenêtre distante, d'un serveur vnc ou du 3ème bureau de l'environnement de bureau cube. Fonctionne juste.

Vous pouvez y jouer en utilisant le sommeil pour de meilleurs tests sleep 3; xdotool click 1+2; xdotool getactivewindow .

J'ai vu que getwindowsfocusrenvoie la même valeur quegetactivewindow .

Si vous effectuez les clics manuellement, vous verrez le menu contextuel, mais cliquez sur 1 + 2 déclenche les deux clics au moment où vous cliquez sur l'emplacement actuel de la souris et obtenez l'ID souhaité.

Essayez-le :)

m3nda
la source
1
Cela donne à l'ID de la fenêtre active (où que la fenêtre peut être), peu importe si oui ou non cette fenêtre active est sous le pointeur de la souris. Selon le libellé de la question: "... trouver l'ID de la fenêtre X sous le pointeur de la souris ..." (où que soit la souris ).
Peter.O
1
Merci pour la correction, vous avez raison. Mis à jour . Je mélangeais le concept de getmouselocation avec activewindow, mais de toute façon, xdotool est assez cool.
m3nda
1

Si vous avez accès à python-xlib , voici un équivalent plus court et plus pythonique à la réponse de Gilles:

from Xlib.display import Display

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

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

J'ai joué avec la réponse de Peter.O et j'ai trouvé:

xdotool click 1|xwininfo|grep 'Window id:'
Ikem Krueger
la source
1
Cela envoie un clic de souris, donc ce serait par exemple cliquer sur un bouton où se trouve le curseur de la souris. Il signalerait par ailleurs la fenêtre dans laquelle se trouve le curseur si vous utilisez le clic pour vous concentrer, mais l'envoi d'un événement de clic est perturbateur.
Gilles 'SO- arrête d'être méchant'
0

ArchWiki a une bonne réponse à cela:

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

L' utilisation que sedvous pouvez le faire en une seule ligne, ce qui est probablement la façon la plus lisible pour le faire:

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

Notez qu'il xdotoolmanquait dans mon Debian minimal X11 alors qu'il xpropétait inclus (de même sedbien sûr).

Si vous ne voulez pas créer de fork sedni grepeffectuer la transformation de texte entièrement bash, ce qui est peut-être un peu plus sûr au cas où la sortie de xpropchange un peu:

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

Quoi qu'il en soit, c'est toujours une façon étrange d'archiver une tâche aussi simple.

Tino
la source
3
Cela donne l'ID de la fenêtre active au lieu de la fenêtre sous le pointeur de la souris.
Peter.O
@ Peter.O Vous avez raison, cela retourne la fenêtre active. Désolé pour la mauvaise réponse, mais avec mes tests, cela a fonctionné - probablement parce que j'avais focus-suit-mouse sur.
Tino
0
xprop -root 2>/dev/null | sed -n '/^_NET_ACTIVE_WINDOW/ s/.* // p'
bleuté
la source
1
Cela donne l'ID de la fenêtre active au lieu de la fenêtre sous le pointeur de la souris.
Peter.O
Oh, je supposais une mise au point bâclée (la mise au point suit la souris) ici.
blueyed
@blueyed Focus est sur les fenêtres actives, et ces fenêtres répondent au CLAVIER. La souris est suivie / suivie par X11 en tant que serveur, et lorsque vous cliquez sur une fenêtre, x11 définit le gestionnaire de fenêtres sur les fenêtres cliquées. Le focus ne suit pas vraiment la souris. Vous pouvez vérifier l'exécution à xdotool getwindowsfocuspartir d'une console et déplacer la souris. La valeur serait la même jusqu'à ce que vous cliquiez sur la souris ou que vous interagissiez avec le clavier (alt + tab, etc.)
m3nda