كيفية التعرف على مستوى عال ويندوز X11 باستخدام xlib؟

StackOverflow https://stackoverflow.com/questions/1201179

  •  05-07-2019
  •  | 
  •  

سؤال

وأنا أحاول الحصول على قائمة بجميع أعلى سطح المكتب ويندوز مستوى في جلسة X11. أساسا، أريد الحصول على قائمة من جميع النوافذ التي تظهر في مديري نافذة UI تبديل التطبيق (فتح عادة عندما يقوم المستخدم بالضغط على ALT + TAB).

وأنا لم تفعل أي البرمجة X11 من قبل، ولكن حتى الآن لقد تمكنت من تعداد خلال قائمة النافذة بأكملها، مع رمز ويبدو أن شيئا من هذا القبيل:

void CSoftwareInfoLinux::enumerateWindows(Display *display, Window rootWindow)
{
    Window parent;
    Window *children;
    Window *child;
    quint32 nNumChildren;

    XTextProperty wmName;
    XTextProperty wmCommand;

    int status = XGetWMName(display, rootWindow, &wmName);
    if (status && wmName.value && wmName.nitems)
    {
        int i;
        char **list;
        status = XmbTextPropertyToTextList(display, &wmName, &list, &i);
        if (status >= Success && i && *list)
        {
            qDebug() << "Found window with name:" << (char*) *list;
        }

        status = XGetCommand(display, rootWindow, &list, &i);
        if (status >= Success && i && *list)
        {
            qDebug() << "... and Command:" << i << (char*) *list;
        }

        Window tf;
        status = XGetTransientForHint(display, rootWindow, &tf);
        if (status >= Success && tf)
        {
            qDebug() << "TF set!";
        }

        XWMHints *pHints = XGetWMHints(display, rootWindow);
        if (pHints)
        {
            qDebug() << "Flags:" << pHints->flags
                    << "Window group:" << pHints->window_group;
        }
    }

    status = XQueryTree(display, rootWindow, &rootWindow, &parent, &children, &nNumChildren);
    if (status == 0)
    {
        // Could not query window tree further, aborting
        return;
    }

    if (nNumChildren == 0)
    {
        // No more children found. Aborting
        return;
    }

    for (int i = 0; i < nNumChildren; i++)
    {
        enumerateWindows(display, children[i]);
    }

    XFree((char*) children);
}

ويسمى enumerateWindows() في البداية مع نافذة الجذر.

وهذا يعمل، بقدر ما أنها تطبع معلومات عن مئات من النوافذ - ما أحتاج، هو العمل على الممتلكات التي أستطيع أن استجواب لتحديد ما إذا كان Window معين هو نافذة تطبيق سطح المكتب المستوى الأعلى (غير متأكد ما المصطلحات الرسمي)، أم لا.

ويمكن لأي شخص أن يلقي بعض الضوء على هذا؟ وكانت جميع الوثائق المرجعية التي وجدتها للبرمجة X11 الجافة بشكل رهيب، ومن الصعب أن نفهم. ربما شخص ما يمكن أن يشير إلى أن تكون أفضل للموارد؟

هل كانت مفيدة؟

المحلول

ولدي حل!

حسنا، من النوع.

إذا مدير نوافذك يستخدم طويلة تلميحات مدير النوافذ (EWMH)، يمكنك الاستعلام نافذة الجذر باستخدام "_NET_CLIENT_LIST" ذرة. هذه القائمة returna النوافذ العميل مدير النافذة إدارة. لمزيد من المعلومات، راجع هنا .

ولكن هناك بعض القضايا مع هذا. لبداية، مدير النوافذ في استخدام يجب أن يدعم EWMH. KDE و GNOME القيام به، وأنا متأكد من أن بعض والآخرون كذلك. ومع ذلك، أنا متأكد من أن هناك العديد من التي لا تفعل ذلك. أيضا، لقد لاحظت وجود عدد قليل من القضايا مع KDE. في الأساس، لا يحصلون تضمنت بعض التطبيقات غير كيدي في القائمة. على سبيل المثال، إذا قمت بتشغيل xcalc تحت KDE فإنه لن تظهر في هذه القائمة.

وإذا كان أي شخص يمكن أن توفر أي تحسينات على هذه الطريقة، وسأكون سعيدا للاستماع لهم. للإشارة، يتم سرد رمز أنا باستخدام أدناه:

    Atom a = XInternAtom(m_pDisplay, "_NET_CLIENT_LIST" , true);
    Atom actualType;
    int format;
    unsigned long numItems, bytesAfter;
    unsigned char *data =0;
    int status = XGetWindowProperty(m_pDisplay,
                                rootWindow,
                                a,
                                0L,
                                (~0L),
                                false,
                                AnyPropertyType,
                                &actualType,
                                &format,
                                &numItems,
                                &bytesAfter,
                                &data);

    if (status >= Success && numItems)
    {
        // success - we have data: Format should always be 32:
        Q_ASSERT(format == 32);
        // cast to proper format, and iterate through values:
        quint32 *array = (quint32*) data;
        for (quint32 k = 0; k < numItems; k++)
        {
            // get window Id:
            Window w = (Window) array[k];

            qDebug() << "Scanned client window:" << w;
        }
        XFree(data);
    }

نصائح أخرى

لتوسيع على الحل السابق، إذا كنت ترغب في ذلك الحصول على أسماء نافذة:

// get window Id:
Window w = (Window) array[k];

char* name = '\0';
status = XFetchName(display, w, &name);
if (status >= Success)
{
    if (name == NULL)
        printf("Found: %ul  NULL\n", w);
    else
        printf("Found: %ul  %s\n", w, name);
}
XFree(name);

إذا لم يكن لديك لاستخدام Xlib، وذلك باستخدام gdk_screen_get_window_stack() GDK وgdk_window_get_window_type() قد تساعدك على الخروج لاحتياجاتك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top