我需要检查(在我的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。
正如其名称所说,这是正常的,该属性仅表示窗口是否被隐藏(例如因为它被最小化)。
如果你想检查你上面的其他窗口并隐藏它的一部分,你必须手动完成。
例如,这会获得所有顶级窗口的列表:
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)。