Reputation: 22116
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
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
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
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