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

Ste*_*ger 3 c linux x11 gtk xlib

使用波纹管代码,我在X11上激活一个窗口.

我正在使用FindWindow来获取窗口句柄,它工作得很好.然后我想把指定的窗口放在前台.为此,我使用XRaiseWindow.

XRaiseWindow(display, wdThisWindow);
Run Code Online (Sandbox Code Playgroud)

但是,XRaiseWindow在某些窗口上不起作用(很多,但不是全部).我想这是因为他们的override_redirect WindowAttribute没有设置为true.所以我使用XChangeWindowAttributes将此属性设置为true.现在,XRaiseWindow将所有窗口都带到了顶部.问题是,EyeOfGnome(图片浏览器)和所有其他应用程序都丢失了顶部的标题栏...(你知道,右边有一个关闭控件的那个......).更糟糕的是,窗户不再出现在后台......

我想如果我在提升窗口后设置了override_redirect属性,问题就会消失.但是......问题现在已经从所有应用程序(例如gnome-terminal)消失了 - 除了EyeOfGnome(图片查看器)......

我错过了什么,或者这是一个EyeOfGnome问题,还是一般的GTK问题?

这是导致问题的部分代码:

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);
Run Code Online (Sandbox Code Playgroud)

这是完整的代码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

Hav*_*c P 6

正如ninjalj所提到的,你所要做的就是使用EWMH规范中的协议,而不是制作这些原始的X协议请求.你在这里做的事情会让GTK +和窗口管理器混淆.

具体来说,你想要做的是发送_NET_ACTIVE_WINDOW客户端消息,源指示(http://standards.freedesktop.org/wm-spec/wm-spec-1.4.html#sourceindication)可能会说你'寻呼机.

顺便提一下,有一个名为libwnck的库(我最初编写但其他人现在维护)将为您完成所有这些工作.即使您不使用它,您也可以查看其源代码以了解如何执行操作.