X11 lib - 如何获取当前window的PID?

X11 lib - How to obtain PID of the current window?

如何使用X11 lib获取当前window的PID?

我尝试检查 window 及其父项的 _NET_WM_PID 属性,但它始终未设置。

由于 X11 团队做出的架构决策,它无法可靠地完成。例如,创建 window 的进程甚至可能与 X11 服务器不在同一台机器上(谁知道 运行 所在机器的 OS 是否有概念PID的?);除此之外,X11 中并没有真正的 "ownership" 概念,因为任何程序都可以对任何 window.

做任何事情

X11 的 PID 没有很好的获取方式window;如果有它也不会立即有用,因为不能保证该进程在同一台机器上,甚至可能无法从您的进程 运行 所在的机器上解析。

旧的 xhost 机制实际上已从现代用法中消失,但这个概念非常活跃。 ssh -X 被大量使用,您可能不得不处理这样一个事实,即您的进程和目标进程在 ssh -X 的不同实例下都是 运行,可能在不同的用户下。这没有留下解决目标的路径。

但是,如果您是因为需要终止进程而来到这里,那么您(有点)走运了。通过在目标 window.

上调用 XKilLClient,可以从 X11 session(在默认处理程序中终止它)转储该进程
int XKillClient(Display *display, XID resource);

第一个参数是您与 X 服务器的连接。第二个参数是您想要离开的进程的任何 window(或任何其他资源)。有关详细信息,请参阅 man 3 XKillClient

看完评论,觉得有必要指出_NET_WM_PID完全不靠谱。此时我的桌面上有一个 window,_NET_WM_PID 报告 1。这现在听起来像是一个可怕的 XY 问题。检索 属性 的 C API 函数是 XGetWindowProperty,您可以调用它来获取诸如 window 标题之类的东西。

最后,我弄清楚了我做错了什么。 代码改编自 ARBTT:

getParent :: Display -> Window -> IO Window
getParent dpy w = do
  (_, parent, _) <- queryTree dpy w `catchIOError` const (return (0,0,[]))
  return parent

followTreeUntil :: Display -> (Window -> IO Bool) -> Window -> IO Window
followTreeUntil dpy cond = go
  where go w = do
          match <- cond w
          if match
            then return w
            else
              do p <- getParent dpy w
                 if p == 0 then return w
                           else go p

getFocusedWindowPID :: Display -> IO String
getFocusedWindowPID d = do
  (w, _) <- getInputFocus d
  wt <- followTreeUntil d (hasCorrectPID d) w
  getWindowPID d wt

getWindowPID :: Display -> Window -> IO String
getWindowPID d w = do
  nWP <- internAtom d "_NET_WM_PID" False
  pid' <- getWindowProperty32 d nWP w
  let pid = case pid' of
              Just [pid''] -> show pid''
              _            -> ""
  return pid

hasCorrectPID :: Display -> Window -> IO Bool
hasCorrectPID d w = do
  pid <- getWindowPID d w
  return $ pid /= ""

printPIDs :: IO ()
printPIDs = do
  d <- openDisplay ""
  pid <- getFocusedWindowPID d
  print pid
  closeDisplay d
  threadDelay 1000000
  printPIDs

这将每秒显示一次焦点 window 的 PID。