我需要检查(在我的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。
答案 0 :(得分: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
原子),消除当前桌面上未显示的任何窗口。_NET_WM_STATE
原子,在列表中寻找_NET_WM_STATE_HIDDEN
原子)。