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

时间:2018-04-22 16:28:48

标签: haskell x11 pid

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

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

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

没有好办法获得X11窗口的PID;并且如果它不会立即有用,因为该过程不能保证在同一台机器上,甚至可能无法从您的过程运行的机器上解析。

旧的xhost机制实际上已经从现代使用中消失了,但这个概念非常活跃。 ssh -X非常有用,您可能需要处理这样一个事实:您的流程和目标流程都在ssh -X的不同实例下运行,可能位于不同的用户之下。这没有留下解决目标的路径。

但是,如果你因为需要杀死这个过程来到这里,那么你很幸运。通过在目标窗口上调用XKilLClient,可以从X11会话(在默认处理程序中终止它)转储该进程。

int XKillClient(Display *display, XID resource);

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

在阅读评论后,我觉得我不得不指出_NET_WM_PID完全不可靠。此时我的桌面上有一个窗口_NET_WM_PID报告1.这听起来像是一个可怕的XY问题。用于检索属性的C API函数是XGetWindowProperty,您可以调用它来获取窗口标题等内容。

答案 2 :(得分:0)

最后,我弄明白我做错了什么。 代码改编自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

这将每秒显示一次聚焦窗口的PID。