Xlib的。检查窗口是否重叠

问题描述 投票:1回答:1

我需要检查(在我的C ++应用程序中)应用程序的窗口是否被另一个窗口重叠(部分或完全)。如何使用xlib获取此信息?

我尝试获取窗口的WM_STATE属性并将其与NormalState进行比较。但是,当我重叠目标窗口时,我的条件(state != NormalState)没有被执行。我还尝试将_NET_WM_STATE属性与_NET_WM_STATE_HIDDEN进行比较,这种方法没有给出必要的结果。

我尝试实现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;
}

此代码始终返回true。

c++ x11 xlib
1个回答
1
投票

正如其名称所说,这是正常的,该属性仅表示窗口是否被隐藏(例如因为它被最小化)。

如果你想检查你上面的其他窗口并隐藏它的一部分,你必须手动完成。

例如,这会获得所有顶级窗口的列表:

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

你需要:

  • 找出您自己的窗口在列表中的位置。在堆叠顺序中位于其上方的任何窗口。
  • 查询您上方每个窗口的桌面(_NET_WM_DESKTOP atom),消除当前桌面上未显示的任何窗口。
  • 查询你上面每个窗口的显示状态(_NET_WM_STATE atom,在列表中查找_NET_WM_STATE_HIDDEN atom)。
  • 查询您上面显示的每个窗口的大小。如果你想考虑非矩形窗口,可能使用Shape extension
  • 检查其中任何一个是否与您自己的显示区域相交。
© www.soinside.com 2019 - 2024. All rights reserved.