19

有谁知道如何获取顶部活动窗口的 PID,然后如何使用 PID 获取窗口的属性?我的意思是进程名称、程序名称等属性。

我在 Linux (Ubuntu 9.10) 下使用 Qt。

4

9 回答 9

25

linux call xprop 中有一个命令,它是一个用于在 X 服务器中显示窗口属性的实用程序。在 linuxxprop -root中为您提供了根窗口属性以及其他活动程序。然后您可以使用以下命令获取活动窗口的 ID:

xprop -root | grep _NET_ACTIVE_WINDOW\(WINDOW\)

获取活动窗口 ID(在行首没有“_NET_ACTIVE_WINDOW(WINDOW): window id #”),请使用以下命令:

xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}'

现在您可以将此命令输出保存在用户定义的变量中:

myid=xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}'

xprop 有一个属性调用-id。此参数允许用户在命令行上选择窗口 ID。我们应该在输出中寻找 _NET_WM_PID(CARDINAL) ......所以我们使用这个命令:

xprop -id $myid | awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}'

这为您提供了最顶层的活动窗口进程 ID。

变得更加狡猾,只需 1 个命令即可完成所有操作...:

 xprop -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}') | awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}'

现在我可以通过我的 C++ 程序(在 linux 中)使用 popen 函数运行这些命令,获取标准输出并打印或保存它。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;
}
于 2010-01-12T20:51:03.237 回答
19

关于 X 的一件事是它是网络透明的。很可能显示在顶部的实际窗口(具有焦点)正在运行在您自己以外的机器上,在这种情况下,在窗口内运行的进程的进程 ID 在您的机器上将毫无意义。

你能详细说明你想做什么吗?我认为这里缺少一些细节。理想情况下,您应该在 X 级别而不是特定于机器的级别上工作。

于 2010-01-11T16:51:20.837 回答
6

我参加聚会很晚了,但我遇到了类似的问题,我认为这可以帮助遇到同样问题的其他人。有一个命令行技巧可以做到这一点,您可以尝试执行它,或者执行它以将输出重定向到您的代码

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 - Stack Overflow - Mozilla Firefox"

WM_CLASS(STRING) = "Navigator", "Firefox"
于 2012-11-02T05:41:14.033 回答
6

窗口所有者的 PID 存储在 X 属性 _NET_WM_PID 中。请注意,这只是一个事实上的标准。

您必须先找到窗口的 id,然后才能查询属性。我不知道 QT 对此提供了任何抽象,因此您可能必须使用 xlib 或 xcb。

使用初学者工具xprop

于 2010-01-11T11:48:37.383 回答
5

xlibXGetInputFocus会告诉你哪个窗口有焦点,这可能比哪个窗口更有趣。参照。Xfree86 的XGetInputFocus 手册页

如果它真的是最顶层的窗口,而不是你所追求的焦点窗口,那么,我认为没有一个简单的调用可以做到这一点,因为 xlib 似乎没有提供任何查询全局的方式堆叠顺序,这是一种数据结构,可以告诉您哪些窗口在哪些其他窗口之前。

一旦你有正确的窗口 id,xprop将在 _NET_WM_PID_ 下列出 pid - 尽管并非所有窗口都有这样的属性......

后记更多想法;很久没有想了xlib……

总结一下:

  1. X 没有在窗口 id 和 pid 之间提供任何可靠的关联,并且正如 Noufal 所观察到的,在 X 桌面上提供的窗口可能来自许多不同的机器,并且两个远程客户端可能碰巧使用相同的 PID,因为它只是每个唯一的机器。参照。如何从进程 ID 获取 X11 窗口?

  2. X 似乎没有提供一个界面来询问哪个是最顶层的窗口,或者一个窗口是否遮挡了另一个窗口。同样具有特权访问... Cf。如何使用 xlib 识别顶级 X11 窗口?

  3. 常用的窗口管理器和 Qt 不授予您对 X 的特权访问权限

  4. 如果没有找到最顶层窗口的方法,以及窗口 id 与匹配 pid 的可靠关联,我们就无法解决这个问题。

  5. 我们可以找到哪个窗口有焦点,这可能就是我们想要的。但同样,没有 pid 映射的 wid ...

所以,很抱歉,它似乎无法完成。

于 2010-01-11T14:21:46.550 回答
3

我正在投票赞成Michel Kogan 的回答,并添加了这个简洁的摘要:

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、命令名称(仅可执行名称)、命令及其所有参数。

于 2011-12-31T14:38:08.107 回答
2

我在终端上运行这个命令:

sleep 5s; ps -Flwwp $(xdotool getwindowpid $(xdotool getwindowfocus))

运行它,将焦点切换到相关窗口,等待 5 秒,然后返回终端。瞧!

于 2020-05-17T07:56:05.503 回答
0

将 xprop 的要点提取到https://github.com/mondalaci/current-window-linux

有效,但有时会出现段错误 - 需要修复和清理。

于 2013-08-05T16:50:17.843 回答
0

安装 wmctrl(来自存储库)。wmctrl -lp可能是你想要的。如果您的程序需要它,您可以随时查看源代码。

于 2010-01-11T16:45:53.297 回答