Răzvan Flavius Panda
Răzvan Flavius Panda

Reputation: 22116

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

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

I tried checking the _NET_WM_PID property of the window and its parents and it was always unset.

Upvotes: 0

Views: 1387

Answers (3)

Răzvan Flavius Panda
Răzvan Flavius Panda

Reputation: 22116

In the end, I figured out what I was doing wrong. Code adapted from 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

This will display the PID of the focused window once every second.

Upvotes: 0

Joshua
Joshua

Reputation: 43327

There is no good way to get the PID of an X11 window; and if there were it would not be immediately useful because the process is not guaranteed to be on the same machine, and may not even be resolvable from the machine your process is running on.

The old xhost mechanism is virtually gone from modern usage, but the concept is very much alive. ssh -X is very much in use and you may have to deal with the fact that both your process and the target process are running under different instances of ssh -X, potentially under different users. This leaves no path to resolve target.

However, if you got here because you need to kill the process, you are (kind of) in luck. The process can be dumped from the X11 session (which terminates it in the default handler) by calling XKilLClient on the target window.

int XKillClient(Display *display, XID resource);

The first argument is your connection to the X server. The second argument is any window (or any other resource) of the process you want gone. See man 3 XKillClient for more details.

After reading comment, I feel like I am obliged to point out that _NET_WM_PID is completely unreliable. At this moment I have a window on my desktop for which _NET_WM_PID reports 1. This now sounds like a horrible XY problem. The C API function to retrieve a property is XGetWindowProperty, which you would call to get things like window title.

Upvotes: 1

Daniel Wagner
Daniel Wagner

Reputation: 153222

It can't be reliably done, due to architectural decisions made by the X11 team. For example, the process that created a window may not even be on the same machine as the X11 server (and who knows if the OS of the machine it's running on even has a concept of PIDs?); and besides that there's not really a concept of "ownership" in X11, as any program can do anything to any window.

Upvotes: 3

Related Questions