How do I bring a processes window to the foreground on X Windows? (C++)

How do I bring a processes window to the foreground on X Windows? (C++)

I have the PID for the process (and the name), I want to bring it to the front on linux (ubuntu). On mac I would simply do SetFrontProcess(pid), on windows I'd enumerate the windows, pick out the one I wanted, and call SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); but I'm at a loss of what to do on linux. I've looked at X Lib a bit, but most/all of those functions seem to operate on windows inside your process.

Edit: Using bdk's answer I added these helpers to my code to get the Window

bool searchHelper(Display* display, Window w, Atom& atomPID, unsigned long pid, Window& result) {     bool ret = false;      Atom atomType;     int format;     unsigned long nItems;     unsigned long bytesAfter;     unsigned char* propPID = 0;     if (Success == XGetWindowProperty(display,w,atomPID,0,1,False,XA_CARDINAL,&atomType,&format,&nItems,&bytesAfter,&propPID))     {         if (propPID != 0)         {             if (pid == *((unsigned long *)propPID))             {                 result = w;                 ret = true;             }             XFree(propPID);         }     }      if (ret)         return ret; //we found we can stop      //check the children of the window     Window wRoot;     Window wParent;     Window *wChild=NULL;     unsigned nChildren=0;     if (XQueryTree(display, w, &wRoot, &wParent, &wChild, &nChildren) != 0 )     {         for (unsigned i=0; i<nChildren; ++i)         {             ret = searchHelper(display, wChild[i], atomPID, pid, result);             if (ret)                 break;         }     }     return ret; }  bool getWindowFromPid(unsigned long pid, Display* display, Window& result) {     Window window = XDefaultRootWindow(display);     Atom atomPID = XInternAtom(display, "_NET_WM_PID", true);     if (atomPID == None)     {         qDebug("XInternAtom failure");         return false;     }     return searchHelper(display, window, atomPID, pid, result); } 

Now I get the window successfully, but when I do the following

if (getWindowFromPid(pid,display,window)) {     qDebug("Found window ID:%d", window);     int result = XRaiseWindow(display,window);     qDebug("XRaiseWindow returned:%d", result); } 

XRaiseWindow returns 1 (BadRequest). The documentation for XRaiseWindow does not mention the return code of BadRequest being a possible result. I'm not sure what is wrong. Am I not allowed to call it for windows in a different process? Is this focus steeling prevention hampering me? Any thoughts?

Edit edit:

So looking at what xwininfo.c does when you call it with -frame I changed my code as follows based on bdk's suggestion.

if (getWindowFromPid(pid,display,window))     {         qDebug("Found window ID:%d", window);          //Need the windowmanger frame (or parent) id not window id         Window root, parent;         Window *childlist;         unsigned int ujunk;         int status = XQueryTree(display, window, &root, &parent, &childlist, &ujunk);         if (status && parent && parent != root)         {             qDebug("Found frame window ID:%d",parent);             window = parent;         }          XSetWindowAttributes xswa;         xswa.override_redirect=True;         int result = XChangeWindowAttributes (display,window,CWOverrideRedirect,&xswa);         qDebug("XChangeWindowAttributes returned:%d", result);         result = XRaiseWindow(display,window);         qDebug("XRaiseWindow returned:%d", result);     }     else         qDebug("unable to find the window for the pid"); 

At this point I do find the window frame ID, but I get a return code of "1" from both XChangeWindowAttributes and XRaiseWindow. Am I just not allowed to modify another process' window?

Passing the shell to a child before aborting


Can read(2) return zero when not at EOF?
I haven't tried this myself, but putting these two methods together may work:.
TEvent.WaitFor in Kylix
The XRaiseWindow API Call in xlib lets you raise a Window to the front if you know the Window ID..
How to create a new Linux kernel scheduler
How can I implement an bad list in a WebService using PHP
This stackoverflow answer explains how to get a Window ID from a PID:.
Difference between libcurl and libsoup [closed]
How to get an X11 Window from a Process ID?.
Talk to VM through host operating system
Authenticating from Java (Linux) to Active Directory using LDAP WITHOUT servername
I've had limited success with XRaiseWindow.

The Following program does work under twm window manager, but not ion which I usually use.

The Window Manager must have ways of preventing applications from 'popping up'.

To make this work, i also had to pass it the Window ID of the Window Manager's frame for the window, not the window itself.

run xwininfo -frame and click on the window and you get the frame ID instead, compile this program with gcc test.c -lX and pass it that hexid on the command line and it will raise the window..
 #include <stdio.h>  #include <stdlib.h>  #include <X11/Xlib.h>   int main(int argc, char **argv)  {    Display *dsp = XOpenDisplay(NULL);    long id = strtol(argv[1], NULL, 16);    XSetWindowAttributes xswa;    xswa.override_redirect=True;    XChangeWindowAttributes (dsp,id,CWOverrideRedirect, &xswa);    XRaiseWindow ( dsp, id );    XCloseDisplay ( dsp );  } 


From the bash command line, you could also use the terrific xdotool, which lets you specify the following to raise the XBMC window and type a backslash into it:.
xdotool search --name 'XBMC Media Center' windowactivate  --sync key backslash 
This program has an actual library under it, libxdo2, which you could use instead if XRaiseWindow fails you.

I understand that libxdo goes to some lengths to always raise the window, regardless of windowmanager.



I had this issue in my application as well, so here's the solution.. To raise the window you need not only to raise it, but you also need to notify the WM about it.

The following code could be used:.
        // This is how to get it in Qt; if you don't use it,         // you can call XOpenDisplay and get it from there;         Display * display = x11Info().display();          // Main window identifier of your application         WId win = winId();          XEvent event = { 0 };         event.xclient.type = ClientMessage;         event.xclient.serial = 0;         event.xclient.send_event = True;         event.xclient.message_type = XInternAtom( display, "_NET_ACTIVE_WINDOW", False);         event.xclient.window = win;         event.xclient.format = 32;          XSendEvent( display, DefaultRootWindow(display), False, SubstructureRedirectMask | SubstructureNotifyMask, &event );         XMapRaised( display, win ); 


I thought this would be easy since /proc seemingly has the required data but /proc/${pid}/environ doesn't provide the correct window ID since it is usually the child of the parent who really owns the window where the process is running.

To get the proper windowid you need to parse the xwininfo output then you can use xdotool to change the focus.

CMD_PID=<your pid here> && while IFS= read -r -d '' var; do  if grep -q "^WINDOWID=" <<< "$var"; then   winid=$(printf '0x%x\n' $(sed 's/WINDOWID=//' <<< "${var}"))  child_cnt=0 && IFS=$(echo -en "\n\b") && for a in $(xwininfo -root -tree | tac | sed -n "/${winid}/,\$p"); do   grep -q -i "children" <<< "${a}" && let child_cnt+=1  ((${child_cnt} == 2)) && real_winid=$(grep -o '0x[^ ]*' <<< "${last_line}") && break  last_line="${a}"  done   xdotool windowraise ${real_winid}   break  fi  done < /proc/${CMD_PID}/environ 

76 out of 100 based on 76 user ratings 226 reviews