2010-02-12 10 views
29

Dado un proceso de iD de XX, me gustaría tener una lista de identificadores de ventanas donde _NET_WM_PID = XX. Aún mejor sería la identificación de ventana activa más antigua si es posible.¿Existe un comando de Linux para determinar los identificadores de ventana asociados con un ID de proceso dado?

Soy muy nuevo en Linux, pero lo que intento hacer es crear un script que tome una línea de comando y ver si ya hay una ventana abierta perteneciente a un proceso invocado con esa misma línea de comando. Si es así, simplemente fije el foco en esa ventana, de lo contrario ejecute la línea de comando para iniciar un nuevo proceso. Mi intención es usar esto en mi escritorio ubuntu, donde engancharé este script en mis comandos de gesto de mouse easystroke, para que, por ejemplo, cada vez que hago un gesto para gmail no obtenga una nueva sesión de Gmail, solo llegar a mi ventana actual de la aplicación gmail chrome. Quizás haya una manera mucho más fácil de hacer todo esto, pero aún no he encontrado el camino para hacerlo.

Con ayuda, he descubierto cómo encontrar un PID para una línea de comando con pgrep y cómo establecer el foco en un identificador de ventana con wmctrl, pero estoy atascado en obtener de PID a la identificación de la ventana.

Respuesta

30

xwininfo y xprop le permite recuperar lo que quiere, pero es un poco complicado.

xwininfo permite recuperar todas las ventanas conocidas, y xprop para consultar X sobre una única ID de ventana para su parámetro _NET_WM_PID.

Hasta el momento, de manera hacky hacerlo sería:

#!/bin/sh 

findpid=$1 

known_windows=$(xwininfo -root -children|sed -e 's/^ *//'|grep -E "^0x"|awk '{ print $1 }') 

for id in ${known_windows} 
do 
    xp=$(xprop -id $id _NET_WM_PID) 
    if test $? -eq 0; then 
     pid=$(xprop -id $id _NET_WM_PID|cut -d'=' -f2|tr -d ' ') 

     if test "x${pid}" = x${findpid} 
     then 
      echo "Windows Id: $id" 
     fi 
    fi 
done 

Resultado:

mycroft:~ $ ./find_windows.sh 1919 
Windows Id: 0x1800748 
Windows Id: 0x181b221 
Windows Id: 0x1803ad5 
Windows Id: 0x181f681 
Windows Id: 0x181f658 
Windows Id: 0x180006d 
Windows Id: 0x1800003 
Windows Id: 0x1800001 
Windows Id: 0x180001e 

Como se verá, un solo proceso puede tener un cierto número de ventanas conocidas, incluso si solo ves uno en tu pantalla.

Quizás deba obtener estas fuentes de herramientas para hacer lo que quiera.

+0

Gracias. Comencé a piratear este código cuando originalmente lo publicaste, pero me quedé boquiabierto y luego desviado (de ahí la aceptación lamentablemente retrasada) ... aún así, esto parecía darme lo que yo deseaba. –

+1

Un trazador de líneas que lo haría (robando a Patrick) cuando podría seleccionar fácilmente la ventana que le interesa es 'xwininfo | sed -e 's/^ * //' | grep -E "Identificación de la ventana" | awk '{print $ 4}' '. La ejecución de xwininfo sin argumentos o conmutadores le permite seleccionar con el mouse la ventana que desea conocer. NOTA: tuve que cambiar el comando grep un poco para RHEL6. – MrMas

20

puede buscar PIDs con wmctrl también, de hecho, y creo que esa es una mejor manera de hacerlo. xwininfo devolverá todo tipo de entidades que parecen ser Windows, pero no las encontrará realmente en su escritorio.

Si lo hace hombre wmctrl , usted encontrará que wmctrl -l listas de todas las ventanas que son realmente visibles en su escritorio con (lo más importante) sus identificadores de ventana y títulos. -p añade PID y -x agregará clases de ventana.

Como dice el manual (RTFM, ¿no?: D), wmctrl también puede buscar a través de algunos de ellos y activar una ventana que coincida con la búsqueda. Sin embargo, no tengo idea de qué determina cuál de todas las posibles coincidencias se devolverá. Por otro lado, puede usar la función de listado proporcionada para escribir un contenedor que hace la búsqueda mejor y posiblemente basado en otras propiedades (como la marca de tiempo del último acceso a la ventana) que puede obtener consultando el proporcionado. Win ID a xprop, por ejemplo.

Estas líneas de código a continuación devuelven el más reciente ejemplo de una ventana de clase compañero-terminal:

XTIME="_NET_WM_USER_TIME" #a shorter name for xprop query that shoul return timestamps 
export TMPDIR=/dev/shm #save tmp files to memory to make it faster 
LST=`mktemp`    #tmp file to store our listing 
wmctrl -lx | awk -F' ' '{printf("%s\t%s \t",$1,$3); for(i=5;i<=NF;i++) printf("%s",$i); printf("\n") }' > $LST #pretty-print our listing of windows into the tmp file 
#To each line of listing, prepend a timestamp acquired via an xprop call 
#Use awk to find a line whose 3rd column (winclass) matches the window class "mate-terminal.Mate-terminal" and among those that do, find the one whose timestamp is the largest 
while read LINE; do ID=`echo "$LINE"|cut -f 1`; TIME=`xprop -id $ID $XTIME`; TIME="${TIME/* = /}"; echo -e "$TIME\t$LINE" ; done <$LST) | awk -v s="mate-terminal.Mate-terminal" '$3 == s {if($1>max){max=$1;line=$0};};END{print line}' 
rm $LST #delete tmp file 

De todos modos, por lo que describes se está construyendo, si yo fuera usted, me gustaría saber qué clase de Windows genera el comando deseado y luego basa mi búsqueda en eso, en lugar de en PID. Alternativamente, podría suponer que el comando CMD posiblemente generará ventanas con un nombre de clase que incluya CMD.

Después de haber encontrado su línea, se debe utilizar el identificador de ventana
para activar la ventana a través de wmctrl.

Espero que esto ayude.

Una nota al margen: he encontrado que xdotool puede hacer búsquedas basadas en nombres de clases y títulos de ventanas también, pero es extremadamente lento. En mi computadora, este script bash (que llama bastantes utilidades externas) es 10 veces más rápido que la alternativa compilada que es xdotool: P.

+1

Pero un beneficio de xdotool es que no necesita un gestor de ventanas "avanzado", por lo que definitivamente vale la pena mencionarlo. –

+0

¿Qué hace 'TIME =" $ {TIME/* = /} "' hacer? –

+0

@JanusTroelsen: sustitución de patrón bash, consulte http://www.tldp.org/LDP/abs/html/parameter-substitution.html#EXPREPL1 –

1

Se puede utilizar:

xdotool getwindowfocus getwindowname 

(Como es:. No es necesario reemplazar esos bonitos nombres con cualquier cosa)

2

Here varias soluciones de gestión de ventanas X11 (incluyendo uno a este problema).

Xwininfo y xprop son buenas herramientas para obtener los ID de todas las ventanas, pero no son las herramientas más fáciles para obtener el ID de la ventana principal asociada con un PID (si eso es posible con ellos). Para obtener el ID de la ventana principal, utilice wmctrl de la siguiente manera:

#!/usr/bin/env bash 
# getwindidbypid 
# 
# Get the ID of a window by PID (if the process has a window). 
# 
# Usage: 
# getwindidbypid <PID> 
# 

while IFS= read line; do 
    if [[ "${line}" =~ (0x)([0-9a-z]+)([ ][- ][0-9]+[ ])([0-9]*) ]]; then 
    winId="${BASH_REMATCH[1]}${BASH_REMATCH[2]}" 
    pid="${BASH_REMATCH[4]}" 
    if [[ "${pid}" -eq "${1}" ]]; then 
     WIND_IDS+=("${winId}") 
    fi 
    fi 
done < <(wmctrl -lp) 

if [ "${#WIND_IDS[@]}" -gt 0 ]; then 
    echo "${WIND_IDS[@]}" 
fi 

Ejemplo:

user ~ $ getwindidbypid 37248 
0x05a00012 

Esta solución se imprimirá varios ID de ventana si más de una ventana primaria se encuentra por wmctrl. Para devolver solo el primero, simplemente cambie [@] a [0] en echo "${WIND_IDS[@]}".

Cuestiones relacionadas