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

Получение pid и деталей для самого верхнего окна

Кто-нибудь знает, как получить PID верхнего активного окна, а затем как получить свойства окна с помощью PID? Я имею в виду такие свойства, как имя процесса, имя программы и т.д.

Я использую Qt под Linux (Ubuntu 9.10).

4b9b3361

Ответ 1

есть команда в вызове 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;
}

Ответ 2

Одна из вещей X - прозрачность сети. Вполне возможно, что фактическое окно, отображаемое вверху (с фокусом), выполняется на машине, отличной от вашей, в этом случае идентификатор процесса, выполняющийся внутри окна, не будет иметь никакого смысла на вашей машине.

Можете ли вы немного рассказать о том, что вы хотите сделать? Я думаю, что здесь есть некоторые недостающие подробности. В идеале вы должны работать на уровне X, а не на конкретной машине.

Ответ 3

PID владельца окна хранится в свойстве X _NET_WM_PID. Обратите внимание, что это только де-факто стандарт.

Сначала нужно найти идентификатор окна, затем вы можете запросить свойство. Я не знаю ни одной абстракции QT для этого, поэтому вам, вероятно, придется использовать xlib или xcb.

Играйте с инструментом xprop для стартеров.

Ответ 4

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...

Итак, извините, похоже, что это невозможно.

Ответ 5

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

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"

Ответ 6

Я голосую Мишель Коганс, и добавив это краткое изложение:

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, имя команды (только имя исполняемого файла), команда со всеми его аргументами.

Ответ 7

Установите wmctrl (из репозиториев). wmctrl -lp может быть тем, что вы хотите. Вы всегда можете взглянуть на источник, если он вам нужен из вашей программы.