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

标签 c linux gtk x11 xlib

使用下面的代码,我在 X11 上激活了一个窗口。

我正在使用 FindWindow 获取窗口句柄,效果很好。 然后我想把指定的窗口放在前台。 为此,我使用 XRaiseWindow。

XRaiseWindow(display, wdThisWindow);

但是,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);

这是完整的代码:

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

最佳答案

正如 ninjalj 提到的,您必须做的是使用 EWMH 规范中的协议(protocol),而不是发出这些原始 X 协议(protocol)请求。您在这里所做的事情会混淆 GTK+ 和窗口管理器。

具体来说,您在这里要做的是发送一条 _NET_ACTIVE_WINDOW 客户端消息,其中包含 来源指示 (http://standards.freedesktop.org/wm-spec/wm-spec-1.4.html#sourceindication) 可能设置为说您是寻呼机。

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

关于c - 在 X11 上激活一个窗口,为什么我会丢失标题栏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5367806/

相关文章:

c - 有右引力标记的例子吗?

go - 知道如何将 GTK-Parasite 与 Go-GTK 一起使用吗?

c++ - 从集合中生成大小为 k 的所有子集

c - 在 C 中写入文件时不需要的字符

linux - 命令 Linux 不工作 "grep"

c - 如何使用 lxdialog 创建 GUI(例如 menuconfig)

linux - 是否可以使用 bash 函数检测参数末尾的空格?

C++ 使用 GTK+ 制作 2D 游戏图形

c - strcpy 段错误

c++ - 32 位或 64 位操作系统如何影响数据类型范围