简体   繁体   English

Xlib。 检查窗口是否重叠

[英]Xlib. Check if window is overlapped

I need to check (in my C++ application) if application's window is overlapped (partially or completely) by another window.我需要检查(在我的 C++ 应用程序中)应用程序的窗口是否与另一个窗口重叠(部分或完全)。 How can I get this info using xlib?如何使用 xlib 获取此信息?

I tried get WM_STATE property of the window and compare it with NormalState.我尝试获取窗口的WM_STATE属性并将其与 NormalState 进行比较。 However, when I overlap target window my condition ( state != NormalState ) wasn't executed.但是,当我重叠目标窗口时,我的条件( state != NormalState )没有被执行。 I also tried to compare _NET_WM_STATE property with _NET_WM_STATE_HIDDEN and this method didn't give needed result.我还尝试将_NET_WM_STATE属性与_NET_WM_STATE_HIDDEN进行比较, _NET_WM_STATE_HIDDEN这种方法没有给出所需的结果。

I tried to implement suggested by spectras solution, and now it looks like working variant(Note: GetWindowProperty is my wrapper around corresponding Xlib function):我试图实现spectras解决方案建议的,现在它看起来像工作变体(注意: GetWindowProperty是我对相应 Xlib 函数的包装):

bool ApplicationHelper::IsWindowOverlapped(const void* hWnd, _XDisplay* pd)
{
    Display* pDisplay = pd == nullptr ? XOpenDisplay(nullptr) : pd;
    if(pDisplay == nullptr)
    {
        return true;
    }
    auto root = XDefaultRootWindow(pDisplay);
    Window parent;
    /*Window* windowList;
    unsigned nchildren;
    if (!XQueryTree(pDisplay, root, &root, &parent, &windowList, &nchildren))
    {
        if(pd == nullptr)
        {
            XCloseDisplay(pDisplay);
        }
        return true;
    }*/

    Atom propCleints = XInternAtom(pDisplay, "_NET_CLIENT_LIST_STACKING", True);
    unsigned long ulBytesReturned = 0;
    Window *windowList = (Window *)GetWindowProperty(pDisplay, root, propCleints, &ulBytesReturned);
    unsigned long nchildren = ulBytesReturned / sizeof(Window);
    int32_t actualDesktop = GetWindowDesktop(pDisplay, (TWindow) hWnd);

    WindowRect targetWindowRect;
    GetWindowRect(hWnd, targetWindowRect, pDisplay);
    GdkRectangle targetGdkRect;
    targetGdkRect.x = targetWindowRect.x;
    targetGdkRect.y = targetWindowRect.y;
    targetGdkRect.width = targetWindowRect.width;
    targetGdkRect.height = targetWindowRect.height;
    bool handleWindow = false;
    bool res = false;
    for (unsigned long i = 0; i < nchildren; ++i)
    {
        auto window = windowList[i];
        if((Window)hWnd == window)
        {
            handleWindow = true;
            continue;
        }
        if(handleWindow)
        {
            if((GetWindowDesktop(pDisplay, window) != actualDesktop) || IsWindowHidden((void*)window, pDisplay))
            {
                continue;
            }
            else
            {
                WindowRect rc;
                GetWindowRect((void*)window, rc, pDisplay);
                GdkRectangle gdkRect;
                gdkRect.x = rc.x;
                gdkRect.y = rc.y;
                gdkRect.width = rc.width;
                gdkRect.height = rc.height;
                if(gdk_rectangle_intersect(&targetGdkRect, &gdkRect, nullptr))
                {
                    res = true;
                    break;
                }
            }
        }
    }
    XFree(windowList);
    if(pd == nullptr)
    {
        XCloseDisplay(pDisplay);
    }

    return res;
}

This code always returns true.此代码始终返回 true。

It's normal, as its name says, that property only signals whether the window is being hidden (for instance because it is minimized).正常情况,正如其名称所说,该属性仅表示窗口是否被隐藏(例如,因为它被最小化)。

If you want to check for other windows above yours and hiding part of it, you'll have to do it manually.如果你想检查你上面的其他窗口并隐藏它的一部分,你必须手动完成。

For instance, this gets a list of all top-level windows:例如,这将获取所有顶级窗口的列表:

auto root = XDefaultRootWindow(display);
Window parent;
Window * children;
unsigned nchildren;
if (!XQueryTree(display, root, &root, &parent, &children, &nchildren)) {
    std::cout <<"Failed to query top level windows list\n";
    return 1;
}

for (unsigned idx = 0; idx < nchildren; ++idx) {
    auto window = children[idx];
    // do something with window
}

XFree(children);

You will need to:您将需要:

  • Find out where your own window is in the list.找出您自己的窗口在列表中的位置。 Any window that comes after it is above in the stacking order.之后的任何窗口都堆叠顺序的上方。
  • Query the desktop of each window above yours ( _NET_WM_DESKTOP atom), eliminate any window not show on current desktop.查询你上面的每个窗口的桌面( _NET_WM_DESKTOP atom),消除当前桌面上未显示的任何窗口。
  • Query the display state of each window above yours ( _NET_WM_STATE atom, looking for _NET_WM_STATE_HIDDEN atom in the list).查询你上面的每个窗口的显示状态( _NET_WM_STATE atom,在列表中查找_NET_WM_STATE_HIDDEN atom)。
  • Query the size of each shown window above yours.查询上面显示的每个窗口的大小。 Possibly using the Shape extension if you want to account for non-rectangular windows如果要考虑非矩形窗口,可以使用Shape 扩展
  • Check whether any of those intersect with your own display area.检查其中任何一个是否与您自己的显示区域相交。

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

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