2010-02-12 19 views
29

Dato un processo iD di XX, mi piacerebbe avere un elenco di qualsiasi ID di finestra in cui _NET_WM_PID = XX. Ancora meglio sarebbe il più vecchio id della finestra ancora attivo se possibile.Esiste un comando linux per determinare gli ID di finestra associati a un determinato ID di processo?

Sono molto nuovo a Linux, ma quello che sto cercando di fare è creare uno script che prenda una riga di comando, e vedere se c'è una finestra già aperta che appartiene a un processo invocato con quella stessa riga di comando. In tal caso, è sufficiente impostare lo stato attivo su quella finestra, altrimenti eseguire la riga di comando per avviare un nuovo processo. La mia intenzione è di usare questo nel mio desktop di Ubuntu, dove collegherò questo script ai miei comandi di gesture del mouse easystroke, in modo che, ad esempio, ogni volta che gestisco per Gmail non ottengo una nuova sessione di Gmail, ho solo essere portato nella mia finestra di app di Chrome Gmail esistente. Forse c'è un modo molto più semplice per fare tutto questo, ma non ho ancora trovato il modo di farlo.

Con l'aiuto, ho capito come trovare un PID per una riga di comando con pgrep e come impostare il focus su un handle di finestra con wmctrl, ma sono bloccato ad andare dal PID all'ID della finestra.

risposta

30

xwininfo e xprop consente di recuperare ciò che si desidera, ma è un po 'complicato.

xwininfo consente di recuperare tutte le finestre note e xprop di interrogare X su un ID di una singola finestra per il parametro _NET_WM_PID.

Finora, un modo hacky per farlo sarebbe:

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

Risultato:

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 

Come si vedrà, un singolo processo può avere un certo numero di finestre noti, anche se ne vedi solo uno sul tuo schermo.

Forse dovresti ottenere queste fonti di strumenti per fare quello che vuoi.

+0

Grazie. Ho iniziato a hackerare con questo codice quando lo hai originariamente pubblicato, ma sono stato ostacolato e poi sviato (da qui l'accettazione purtroppo spiacevolmente) ... tuttavia, sembrava che mi stesse dando solo quello che volevo. –

+1

Un solo liner che lo farebbe (rubando da Patrick) quando potresti facilmente selezionare la finestra che ti interessa è 'xwininfo | sed -e 's/^ * //' | grep -E "ID finestra" | awk '{print $ 4}' '. L'esecuzione di xwininfo senza argomenti o opzioni consente di selezionare con il mouse la finestra che si desidera conoscere. NOTA: ho dovuto modificare un po 'il comando grep per RHEL6. – MrMas

20

è possibile cercare PID con wmctrl troppo, in effetti, e penso che sia un modo migliore per farlo. xwininfo restituirà tutti i tipi di entità che sembrano essere Windows, ma non li troverai sul tuo desktop.

Se fai uomo wmctrl , troverete che wmctrl -l elenca tutte le finestre che sono in realtà visibile sul desktop con (soprattutto) i loro finestra ids e titoli. -p aggiunge PID e -x aggiungerà classi di finestre.

Come dice il manuale (RTFM, a destra?: D), wmctrl può anche cercare tra alcuni di questi e attivare una finestra che corrisponde alla ricerca. Tuttavia, non ho idea di cosa determini quale delle possibili corrispondenze sarà restituita. D'altra parte, è possibile utilizzare la funzione di elenco fornita per scrivere un wrapper che ricerca meglio e possibilmente basato su alcune altre proprietà (come il timestamp dell'ultimo accesso alla finestra) che è possibile ottenere interrogando l'fornito. vincere l'id su xprop, ad esempio.

Queste righe di codice sotto restituire il più recente esempio di una finestra di classe compagno-terminale:

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 

In ogni caso, per la cosa che descrivi si stanno costruendo, se fossi in te, vorrei sapere quale classe di Windows il comando desiderato genera e quindi basa la mia ricerca su quello, piuttosto che su PID. In alternativa, è possibile presumere che CMD genererà probabilmente finestre con un nome di classe che include CMD.

Dopo aver trovato la vostra linea, è necessario utilizzare la finestra di id
per attivare la finestra tramite wmctrl.

Spero che questo aiuti.

Una nota a margine: ho trovato che xdotool può eseguire ricerche in base ai nomi di classi e titoli di finestre, ma è estremamente lento. Sul mio computer, questo script bash (che chiama un paio di programmi esterni) è 10 volte più veloce dell'alternativa compilata che è xdotool: P.

+1

Ma un vantaggio di xdotool è che non ha bisogno di un gestore di finestre "avanzato", quindi vale sicuramente la pena menzionarlo. –

+0

cosa fa 'TIME =" $ {TIME/* = /} "' fare? –

+0

@JanusTroelsen: sostituzione del modello Bash, vedere http://www.tldp.org/LDP/abs/html/parameter-substitution.html#EXPREPL1 –

1

È possibile utilizzare:

xdotool getwindowfocus getwindowname 

(Come è:. Non è necessario sostituire quei nomi dal suono piacevole con qualsiasi cosa)

2

Here sono diverse soluzioni di gestione delle finestre X11 (tra cui uno a questo problema).

Xwininfo e xprop sono buoni strumenti per ottenere gli ID di tutte le finestre ma non gli strumenti più facili per ottenere l'ID della finestra principale associata a un PID (se ciò è possibile anche con essi). Per ottenere l'ID della finestra principale, utilizzare wmctrl nel seguente modo:

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

Esempio:

user ~ $ getwindidbypid 37248 
0x05a00012 

Questa soluzione stamperà più ID finestra se più di una finestra primaria è trovato da wmctrl. Per restituire solo il primo, cambia semplicemente [@] in [0] in echo "${WIND_IDS[@]}".

Problemi correlati