如何在X Windows上将进程窗口置于前台? (C ++) [英] How do I bring a processes window to the foreground on X Windows? (C++)

查看:1429
本文介绍了如何在X Windows上将进程窗口置于前台? (C ++)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有进程的PID(和名称),我想把它带到linux(ubuntu)的前端。在Mac上我只需要做 SetFrontProcess(pid),在窗口上我将枚举窗口,选择一个我想要的,并调用 SetWindowPos hwnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE); 但我失去了在linux上做什么。我看过X Lib有一点,但大多数/所有的这些功能似乎在你的进程中的窗口上操作。

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.

编辑:使用bdk的答案我添加了这些帮助我的代码来获取窗口

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返回1(BadRequest)。 XRaiseWindow的文档没有提到BadRequest的返回代码是一个可能的结果。我不知道是什么问题。我不允许在不同的进程中调用它的窗口?这是焦点钢化预防阻碍我吗?任何想法?

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?

编辑编辑:

所以看看xwininfo.c当你调用它 - 框架我根据bdk的建议改变了我的代码如下。

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");

此时,我找到窗口框架ID,但我得到一个返回代码1从XChangeWindowAttributes和XRaiseWindow。我只是不允许修改另一个进程的窗口?

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?

推荐答案

我没有试过这个,一起可以工作:

I haven't tried this myself, but putting these two methods together may work:

如果你知道窗口ID,xlib中的XRaiseWindow API调用可以将窗口提升到前面。

The XRaiseWindow API Call in xlib lets you raise a Window to the front if you know the Window ID.

http://www.unix.com/man-page / Linux / 3 / XRaiseWindow /

这个stackoverflow回答解释了如何从PID获取窗口ID:

This stackoverflow answer explains how to get a Window ID from a PID:

如何获取X11窗口一个进程ID?

编辑:

我在XRaiseWindow上取得的成功有限。以下程序在twm窗口管理器下工作,但不是我通常使用的离子。窗口管理器必须具有防止应用程序弹出的方法。为了使这个工作,我也不得不传递窗口的窗口管理器的框架的窗口ID,而不是窗口本身。运行xwininfo -frame,然后点击窗口,你得到框架ID,编译这个程序与gcc test.c -lX,并传递它hexid在命令行,它会提高窗口。

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 );
 }

这篇关于如何在X Windows上将进程窗口置于前台? (C ++)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆