【问题标题】:Getting pid and details for topmost window获取最顶层窗口的 pid 和详细信息
【发布时间】:2011-01-03 17:37:01
【问题描述】:

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

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

【问题讨论】:

  • 你的应用知道自己的 pid,这是你想要的吗?
  • QT 不是一种语言,它是一个工具包。 QT 是用 C++ 编写的,但具有许多其他语言的绑定。你在用 C++ 吗?
  • @JamesPolley QT 与一门语言并不完全不同,因为它可以充当“一次编写,到处编译”工具,其中移植诸如 POSIX 调用之类的东西需要为 WinAPI、Android 等编写单独的代码..

标签: linux qt pid xlib


【解决方案1】:

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

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

初学者可以使用工具xprop

【讨论】:

    【解决方案2】:

    xlib 的XGetInputFocus 会告诉你哪个窗口有焦点,这可能比哪个窗口更有趣。参照。 Xfree86 的XGetInputFocus manpage.

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

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

    后记 更多想法;很久没有想到xlib...

    总结一下:

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

    2. X 似乎没有提供一个界面来询问哪个是最顶层的窗口,或者一个窗口是否遮挡了另一个窗口。同样具有特权访问... Cf。 How to identify top-level X11 windows using xlib?

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

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

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

    所以,很抱歉,看来无法完成。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 参见。 wmctrl 关于 -p 选项的说明:“在窗口列表中包含 PID。很少有 X 应用程序支持此功能。”另请注意,WM 可能支持也可能不支持 EWMH; Qt 可以与不一致的 WM 一起使用。
      【解决方案4】:

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

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

      【讨论】:

      • 焦点窗口不必在顶部。
      • 我想拥有焦点是 OP 的意思,但他将他的 WM 配置为只关注凸起的窗口。无论如何,我关于网络透明度的观点是正确的。
      • @Noufal:我同意专注是他可能想要的(见我的回答),但这不是他问的......你可以说 X 服务器的 pid 是正确的 pid情况,因为它是(通常!)侦听端口 6000(或其他)的进程。
      • 他想要客户端的pid。使用窗口的应用程序。不是 X 服务器。我要说的是 X 是网络透明的,因此窗口内进程的 pid 可能没有意义(如果客户端是另一台机器等)。无论您在该服务器上检查哪个窗口,X 服务器的 pid 都将是相同的。我没看到你在开什么车。
      【解决方案5】:

      在 linux call xprop 中有一个命令,它是一个用于在 X 服务器中显示窗口属性的实用程序。在 linux 中,xprop -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;
      }
      

      【讨论】:

      • 但请注意,这通常会失败,因为正如其他几个答案所指出的那样,_NET_WM_PID 是一个通常不存在的属性。
      • 你知道你可以在 xprop 命令行上指定变量吗?比如xprop _NET_WM_PID -id $window_id
      【解决方案6】:

      我正在投票支持Michel Kogan’s answer,并添加以下简明摘要:

      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】:

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

        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"
        

        【讨论】:

          【解决方案8】:

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

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

          【讨论】:

            【解决方案9】:

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

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

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-01-20
              • 2019-08-04
              • 2018-03-11
              • 2012-06-02
              • 2020-10-08
              • 2018-08-04
              相关资源
              最近更新 更多