Xlib.Проверьте, перекрыто ли окно - PullRequest
1 голос
/ 25 марта 2019

Мне нужно проверить (в моем приложении 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.

1 Ответ

1 голос
/ 25 марта 2019

Обычно, как следует из названия, это свойство только сигнализирует о том, скрыто ли окно (например, потому что оно свернуто).

Если вы хотите проверить другие окна над вашим и скрыть часть их, вам придется сделать это вручную.

Например, получается список всех окон верхнего уровня:

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 атом в списке).
  • Запросите размер каждого показанного окна над вашим. Возможно использование расширения Shape , если вы хотите учесть непрямоугольные окна
  • Проверьте, пересекаются ли какие-либо из них с вашей собственной областью отображения.
...