简体   繁体   English

在X11上激活一个窗口,为什么我会丢失标题栏?

[英]Activating a Window on X11, why do I lose the title bar?

Using the bellow code, I am activating a window on X11. 使用波纹管代码,我在X11上激活一个窗口。

I'm using FindWindow to get the window handle, which works just fine. 我正在使用FindWindow来获取窗口句柄,它工作得很好。 Then I want to bring the specified window in the foreground. 然后我想把指定的窗口放在前台。 To do this, I use XRaiseWindow. 为此,我使用XRaiseWindow。

XRaiseWindow(display, wdThisWindow);

However, XRaiseWindow doesn't work on some windows (quite many, but not all). 但是,XRaiseWindow在某些窗口上不起作用(很多,但不是全部)。 I figured this is because their override_redirect WindowAttribute is not set to true. 我想这是因为他们的override_redirect WindowAttribute没有设置为true。 So I used XChangeWindowAttributes to set this property to true. 所以我使用XChangeWindowAttributes将此属性设置为true。 Now, XRaiseWindow brings all windows to the top. 现在,XRaiseWindow将所有窗口都带到了顶部。 The problem is, EyeOfGnome (picture viewer) and all other applications looses the top title bar... (you know, the one with the close control on the right...). 问题是,EyeOfGnome(图片浏览器)和所有其他应用程序都丢失了顶部的标题栏...(你知道,右边有一个关闭控件的那个......)。 And what's even worse, the window doesn't go to the background anymore... 更糟糕的是,窗户不再出现在后台......

I figured if I set back the override_redirect property after I raised the window, the problem would be gone. 我想如果我在提升窗口后设置了override_redirect属性,问题就会消失。 But... The problem is now gone from all applications (such as gnome-terminal) - all except EyeOfGnome (Picture Viewer)... 但是......问题现在已经从所有应用程序(例如gnome-terminal)消失了 - 除了EyeOfGnome(图片查看器)......

Am I missing something, or is this an EyeOfGnome issue, or is it a general GTK issue ? 我错过了什么,或者这是一个EyeOfGnome问题,还是一般的GTK问题?

Here's the problem-causing part of the code: 这是导致问题的部分代码:

XSetWindowAttributes xswa;
xswa.override_redirect = True;
XChangeWindowAttributes(display, wdThisWindow, CWOverrideRedirect, &xswa);
XRaiseWindow(display, wdThisWindow);
xswa.override_redirect = False;
XChangeWindowAttributes(display, wdThisWindow, CWOverrideRedirect, &xswa);
XSetInputFocus(display, wdThisWindow, RevertToNone, CurrentTime);

And this is the complete code: 这是完整的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>



// Info: xwininfo
// I am compiling using 
// gcc -o activate activate.c -L/usr/X11R6/lib -lX11


// ERROR HANDLER, GENERIC
static int ErrorHandler (Display *display, XErrorEvent *error)
{
   //printf ("\r\n error! \r\n");// gcc -o xwinspy lol.c -L/usr/X11R6/lib -lX11
   return 0;
}
// END ERROR HANDLER


// Recursively search through all windows on display
Window SearchWindow(char* szWindowToFind, int level, Display *display, Window rootWindow, int iMatchMode, int showErrors)
{
    Window parent;
    Window *children;
    unsigned int noOfChildren;
    int status;
    int i;
    Window wSearchedWindow = 0;

    char* win_name;
    if (XFetchName(display, rootWindow, &win_name))
    {
            //printf("WinName (Level %d): %s\n", level, win_name);
            if(iMatchMode == 0)
            {
                if( strstr(win_name, szWindowToFind) )
                {
                    return rootWindow;
                }
            }
            else if(iMatchMode == 1)
            {
                if( !strcmp(win_name, szWindowToFind) )
                {
                    return rootWindow;
                }
            }
            else if(iMatchMode == 2)
            {
                if( strcasestr(win_name, szWindowToFind) )
                {
                    return rootWindow;
                }
            }
            else if(iMatchMode == 3)
            {
                if( !strcasecmp(win_name, szWindowToFind) )
                {
                    return rootWindow;
                }
            }
            else 
            {
                if( strstr(win_name, szWindowToFind) )
                {
                    return rootWindow;
                }
            }

    } // End if XFetchName



    status = XQueryTree (display, rootWindow, &rootWindow, &parent, &children, &noOfChildren);

    if (status == 0)
    {
        if (showErrors)
            printf ("ERROR - Could not query the window tree. Aborting.\r\n");
        return;
    }

    if (noOfChildren > 0)
    {
        for (i=0; i < noOfChildren; i++)
        {
            wSearchedWindow = SearchWindow(szWindowToFind, level+1, display, children[i], iMatchMode, showErrors);
            if(wSearchedWindow)
            {
                break;
            }
        }
    } 

    XFree ((char*) children);

    return wSearchedWindow;
} // End Sub EnumerateWindows


Window FindWindow(char* szWindowToFind)
{
    Display *display = XOpenDisplay (NULL);
    int screen = DefaultScreen (display);

    XSetErrorHandler(ErrorHandler);

    Window rootWindow = RootWindow (display, screen);   

    Window wSearchedWindow = SearchWindow(szWindowToFind, 0, display, rootWindow, 0, 0);

    char* win_name;
    if (XFetchName(display, wSearchedWindow, &win_name))
    {
        printf("Found: %s\n", win_name);
    }

    XCloseDisplay (display);
    return wSearchedWindow;
}

void ActivateWindow(char* szWindow)
{
    Window wdThisWindow = FindWindow(szWindow);

    Display *display = XOpenDisplay (NULL);

    char* win_name;
    if (XFetchName(display, wdThisWindow, &win_name))
    {
        printf("Activating: %s\n", win_name);
    }

    XSetErrorHandler(ErrorHandler);

    XSetWindowAttributes xswa;
    xswa.override_redirect = True;
    XChangeWindowAttributes(display, wdThisWindow, CWOverrideRedirect, &xswa);
    XRaiseWindow(display, wdThisWindow);
    xswa.override_redirect = False;
    XChangeWindowAttributes(display, wdThisWindow, CWOverrideRedirect, &xswa);
    XSetInputFocus(display, wdThisWindow, RevertToNone, CurrentTime);

    XCloseDisplay (display);
}



// ENUMARATE THROUGH WINDOWS AND DISPLAY THEIR TITLES
void EnumerateWindows(int level, Display *display, Window rootWindow, int showErrors)
{
    Window parent;
    Window *children;
    unsigned int noOfChildren;
    int status;
    int i;

    char* win_name;
    if (XFetchName(display, rootWindow, &win_name))
    {
            printf("Window-Name (Level %d): %s\n", level, win_name);
    }

    status = XQueryTree (display, rootWindow, &rootWindow, &parent, &children, &noOfChildren);

    if (status == 0)
    {
        if (showErrors)
            printf ("ERROR - Could not query the window tree. Aborting.\r\n");
        return;
    }

    if (noOfChildren > 0)
    {
        for (i=0; i < noOfChildren; i++)
        {
            EnumerateWindows(level+1, display, children[i], showErrors);
        }
    } 

    XFree ((char*) children);
} // End Sub EnumerateWindows


void ListAllWindowsOnScreen()
{
    Display *display = XOpenDisplay (NULL);
    int screen = DefaultScreen (display);

    XSetErrorHandler(ErrorHandler);

    Window rootWindow = RootWindow (display, screen);   

    EnumerateWindows(0, display, rootWindow, 0);
    XCloseDisplay (display);
}


int main(int argc, char *argv[])
{
    ListAllWindowsOnScreen();
    //ActivateWindow("000727");
    return EXIT_SUCCESS;
}

What you have to do, as ninjalj mentions, is use the protocols in the EWMH specification rather than making these raw X protocol requests. 正如ninjalj所提到的,你所要做的就是使用EWMH规范中的协议,而不是制作这些原始的X协议请求。 What you're doing here will confuse the heck out of both GTK+ and the window manager. 你在这里做的事情会让GTK +和窗口管理器混淆。

Specifically, what you want to do here is send a _NET_ACTIVE_WINDOW client message, with the source indication (http://standards.freedesktop.org/wm-spec/wm-spec-1.4.html#sourceindication) probably set to say you're a pager. 具体来说,你想要做的是发送_NET_ACTIVE_WINDOW客户端消息,源指示(http://standards.freedesktop.org/wm-spec/wm-spec-1.4.html#sourceindication)可能会说你'寻呼机。

Incidentally there's a library called libwnck (which I wrote originally but other people now maintain) which will do all this for you. 顺便提一下,有一个名为libwnck的库(我最初编写但其他人现在维护)将为您完成所有这些工作。 Even if you don't use it, you can look at its source code to learn how to do stuff. 即使您不使用它,您也可以查看其源代码以了解如何执行操作。

OverrideRedirect is for windows that bypass the window manager. OverrideRedirect用于绕过窗口管理器的窗口。 The protocol for requesting stacking order changes is described in the ICCCM , section 4.1.5. 请求堆叠订单更改的协议在ICCCM第4.1.5节中描述。 The EWMH spec includes some extensions to this protocol, like layered stacking order and window activation (giving focus and possibly raising the window). EWMH规范包括对该协议的一些扩展,例如分层堆叠顺序和窗口激活(给予焦点并可能提高窗口)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM