Подтвердить что ты не робот

Есть ли команда linux для определения идентификаторов окон, связанных с данным идентификатором процесса?

Учитывая процесс iD XX, я хотел бы иметь список любого идентификатора окна, где _NET_WM_PID = XX. Еще лучше было бы самым старым по-прежнему активным идентификатором окна, если это возможно.

Я очень новичок в Linux, но то, что я пытаюсь сделать, это создать script, который будет использовать командную строку, и посмотреть, есть ли уже открытые окна, принадлежащие процессу, вызванному той же командной строкой, Если это так, просто установите фокус на это окно, иначе выполните командную строку, чтобы получить новый процесс. Я намерен использовать это на своем рабочем столе ubuntu, где я подключу этот script к моим командам жестов мыши easystroke, так что, например, каждый раз, когда я жестом для gmail, я не получаю совершенно новую сессию gmail, Я просто подключился к существующему окну приложения Chrome gmail. Возможно, есть намного более простой способ обойти все это, но я еще не нашел свой путь к этому.

С помощью справки я выяснил, как найти PID для командной строки с pgrep и как установить фокус на дескриптор окна с помощью wmctrl, но я застрял в получении от PID к ID окна.

4b9b3361

Ответ 1

xwininfo и xprop позволяют извлекать то, что вы хотите, но это немного сложно.

xwininfo позволяет извлекать все известные окна и xprop запрашивать X об одном идентификаторе окна для вашего параметра _NET_WM_PID.

До сих пор хакерский способ сделать это:

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

Результат:

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

Как вы увидите, у одного процесса может быть определенное количество известных окон, даже если вы видите только один на вашем экране.

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

Ответ 2

вы можете найти PID с помощью wmctrl тоже, и я думаю, что это лучший способ сделать это. xwininfo вернет всевозможные сущности, которые выглядят как окна, но вы не найдете их на своем рабочем столе.

Если вы человек wmctrl , вы обнаружите, что wmctrl -l перечисляет все окна, которые на самом деле видны на вашем рабочем столе (что наиболее важно) их идентификаторы и названия окон. -p добавляет PID, а -x добавит классы окон.

Как говорится в руководстве (RTFM, правильно?: D), wmctrl также может выполнить поиск по некоторым из них и активировать окно, соответствующее поиску. Однако я не знаю, что определяет, какое из возможных совпадений будет возвращено. С другой стороны, вы можете использовать предоставленную функцию листинга для записи обертки, которая лучше выполняет поиск и, возможно, основывается на некоторых других свойствах (таких как временная метка последнего доступа к окну), которую вы можете получить, запросив предоставленную выигрышную id для xprop, например.

Эти строки кода ниже возвращают самый последний экземпляр окна класса mate-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

Во всяком случае, за то, что вы описываете, вы строите - если бы я был вами, я бы узнал, какой класс окон генерирует ваша желаемая команда, а затем основывает мой поиск на этом, а не на PID. В качестве альтернативы вы можете предположить, что команда CMD может генерировать окна с именем класса, которое включает CMD.

После того, как вы нашли свою строку, вы должны использовать идентификатор окна
для активации окна через wmctrl.

Надеюсь, что это поможет.

Замечание: я обнаружил, что xdotool может выполнять поиск на основе имен классов и заголовков окон, но он очень медленный. На моем компьютере этот bash script (который вызывает довольно много внешних приложений) в 10 раз быстрее, чем скомпилированная альтернатива, которая представляет собой xdotool: P.

Ответ 3

Здесь - несколько решений управления окнами X11 (в том числе и для этой проблемы).

Xwininfo и xprop - хорошие инструменты для получения идентификаторов всех окон, но не самые простые инструменты для получения идентификатора первичного окна, связанного с PID (если это возможно с ними). Чтобы получить идентификатор первичного окна, используйте wmctrl следующим образом:

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

Пример:

user ~ $  getwindidbypid 37248
0x05a00012

Это решение напечатает несколько идентификаторов окон, если wmctrl обнаружит несколько первичных окон. Чтобы вернуть только первый, просто измените [@] на [0] в echo "${WIND_IDS[@]}".

Ответ 4

Вы можете использовать:

xdotool getwindowfocus getwindowname

(Как есть: вам не нужно заменять эти симпатичные имена ничем.)