[英]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:您将需要:
_NET_WM_DESKTOP
atom), eliminate any window not show on current desktop._NET_WM_DESKTOP
atom),消除当前桌面上未显示的任何窗口。_NET_WM_STATE
atom, looking for _NET_WM_STATE_HIDDEN
atom in the list)._NET_WM_STATE
atom,在列表中查找_NET_WM_STATE_HIDDEN
atom)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.