Кто-нибудь знает, как получить PID верхнего активного окна, а затем как получить свойства окна с помощью PID? Я имею в виду такие свойства, как имя процесса, имя программы и т.д.
Я использую Qt под Linux (Ubuntu 9.10).
Кто-нибудь знает, как получить PID верхнего активного окна, а затем как получить свойства окна с помощью PID? Я имею в виду такие свойства, как имя процесса, имя программы и т.д.
Я использую Qt под Linux (Ubuntu 9.10).
есть команда в вызове linux xprop, которая является утилитой для отображения свойств окна на X-сервере. В linux xprop -root
вы получаете свойства корневых окон, а также другие активные программы. то вы можете получить идентификатор активного окна с помощью этой команды:
xprop -root | grep _NET_ACTIVE_WINDOW\(WINDOW\)
чтобы получить только идентификатор активного окна (без "_NET_ACTIVE_WINDOW (WINDOW): id окна #" в начале строки) используйте эту команду:
xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}'
теперь вы можете сохранить этот вывод команды в пользовательской переменной:
myid=xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}'
xprop имеют атрибут -id. Этот аргумент позволяет пользователю выбрать идентификатор окна в командной строке. Мы должны искать _NET_WM_PID (CARDINAL) в выводе... поэтому мы используем эту команду:
xprop -id $myid | awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}'
это дает вам самый высокий активный идентификатор процесса окна.
чтобы быть более трюки и делать все в одной команде...:
xprop -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}') | awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}'
Теперь я могу запускать эти команды через мою программу на С++ (в Linux), используя функцию popen, захватывать stdout и печатать или сохранять его. popen создает канал, чтобы мы могли читать вывод программы, которую мы вызываем.
(вы также можете использовать файловую систему '/proc' и получить более подробную информацию о PID ('/proc/YOUR_PID/status'))
#include <string>
#include <iostream>
#include <stdio.h>
using namespace std;
inline std::string exec(char* cmd) {
FILE* pipe = popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[128];
std::string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
pclose(pipe);
return result;
}
int main()
{
//we uses \\ instead of \ ( \ is a escape character ) in this string
cout << exec("xprop -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\\(WINDOW\\)/{print $NF}') | awk '/_NET_WM_PID\\(CARDINAL\\)/{print $NF}'").c_str();
return 0;
}
Одна из вещей X - прозрачность сети. Вполне возможно, что фактическое окно, отображаемое вверху (с фокусом), выполняется на машине, отличной от вашей, в этом случае идентификатор процесса, выполняющийся внутри окна, не будет иметь никакого смысла на вашей машине.
Можете ли вы немного рассказать о том, что вы хотите сделать? Я думаю, что здесь есть некоторые недостающие подробности. В идеале вы должны работать на уровне X, а не на конкретной машине.
PID владельца окна хранится в свойстве X _NET_WM_PID. Обратите внимание, что это только де-факто стандарт.
Сначала нужно найти идентификатор окна, затем вы можете запросить свойство. Я не знаю ни одной абстракции QT для этого, поэтому вам, вероятно, придется использовать xlib или xcb.
Играйте с инструментом xprop
для стартеров.
xlib XGetInputFocus
расскажет вам, какое окно имеет фокус, что, вероятно, более интересно, чем самое верхнее. Ср Xfree86 XGetInputFocus manpage.
Если это действительно самое верхнее окно, а не окно с фокусом, которое вам нужно, ну, я не думаю, что есть простой вызов сделать это, потому что xlib, похоже, не предлагает никакого способа запрос глобального порядка стекирования, который представляет собой структуру данных, которая сообщает вам, какие окна перед другими.
После того, как у вас есть правый идентификатор окна, xprop
перечислит pid под _NET_WM_PID_ - хотя не все окна имеют такое свойство...
Postscript Другие мысли; долгое время с тех пор, как я думал о xlib
...
Подводя итог:
X не предлагает никакой надежной связи между идентификаторами окон и pids, и, как отмечает Noufal, окна, обслуживаемые на рабочем столе X, могут поступать из разных машин, а два удаленных клиента могут использовать один и тот же PID, так как он уникален только для каждой машины. Ср Как получить окно X11 из идентификатора процесса?
X, похоже, не предлагает интерфейс, спрашивающий, что является самым верхним окном, или одно окно закрывает другое. Аналогично с привилегированным доступом... Ср. Как определить окна верхнего уровня X11 с помощью xlib?
Обычно доступные оконные менеджеры и Qt не предоставляют вам привилегированный доступ к X
Без обоих способов найти самое верхнее окно и надежную связь идентификатора окна с подходящим pid мы не сможем решить вопрос.
Мы можем найти, какое окно имеет фокус, и это, вероятно, то, что мы хотим. Но опять же, без карты wid to pid...
Итак, извините, похоже, что это невозможно.
Я очень поздно опоздал на вечеринку, но у меня была аналогичная проблема, и я думаю, что это может помочь кому-то другому, у кого такая же проблема. Для этого используется командная строка, вы можете попробовать выполнить его или выполнить перенаправление вывода на свой код
xprop -id $(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) _NET_WM_NAME WM_CLASS
дает имя окна, а также имя программы. Например, для этой вкладки это дает мне
_NET_WM_NAME(UTF8_STRING) = "linux - Getting pid and details for topmost window - Qaru - Mozilla Firefox"
WM_CLASS(STRING) = "Navigator", "Firefox"
Я голосую Мишель Коганс, и добавив это краткое изложение:
ps -o pid,comm,args $(xprop -id $(xprop -root -f _NET_ACTIVE_WINDOW 0x " \$0\\n" _NET_ACTIVE_WINDOW | awk "{print \$2}") -f _NET_WM_PID 0c " \$0\\n" _NET_WM_PID | awk "{print \$2}")
Вышеуказанное отобразит следующее для текущего активного окна: PID, имя команды (только имя исполняемого файла), команда со всеми его аргументами.
Установите wmctrl (из репозиториев). wmctrl -lp
может быть тем, что вы хотите. Вы всегда можете взглянуть на источник, если он вам нужен из вашей программы.
Извлечение сущности xprop в https://github.com/mondalaci/current-window-linux
Работает, но иногда segfaults - нужно исправлять и очищать.