2009-07-29 8 views
12

मैं X11 सत्र में सभी शीर्ष स्तर की डेस्कटॉप विंडो की एक सूची प्राप्त करने का प्रयास कर रहा हूं। असल में, मैं विंडो मैनेजर एप्लिकेशन-स्विचिंग यूआई में दिखाए गए सभी विंडो की एक सूची प्राप्त करना चाहता हूं (जब उपयोगकर्ता ALT + TAB दबाता है तो आमतौर पर खोला जाता है)।xlib का उपयोग कर शीर्ष-स्तर 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() साथ प्रारंभ में कहा जाता है:

मैंने कभी नहीं किसी भी X11 प्रोग्रामिंग से पहले कुछ इस तरह दिखता है कि किया है, लेकिन अब तक मैं पूरी विंडो सूची के माध्यम बताना प्रबंधित किया है, कोड के साथ जड़ खिड़की

यह काम करता है, जहां तक ​​यह सैकड़ों खिड़कियों के बारे में जानकारी प्रिंट करता है - मुझे क्या चाहिए, यह निर्धारित करने के लिए कि कौन सी संपत्ति मैं पूछताछ कर सकता हूं यह निर्धारित करने के लिए कि Window एक शीर्ष-स्तरीय डेस्कटॉप एप्लिकेशन विंडो है (सुनिश्चित नहीं है आधिकारिक शब्दावली क्या है), या नहीं।

क्या कोई इस पर कुछ प्रकाश डाल सकता है? एक्स 11 प्रोग्रामिंग के लिए मैंने पाया है कि सभी संदर्भ दस्तावेज बहुत शुष्क और समझने में मुश्किल है। शायद कोई बेहतर संसाधन के लिए इंगित कर सकता है?

उत्तर

11

मेरे पास समाधान है!

ठीक है, तरह।

यदि आपका विंडो प्रबंधक विस्तारित विंडो प्रबंधक संकेत (ईडब्लूएमएच) का उपयोग करता है, तो आप "_NET_CLIENT_LIST" परमाणु का उपयोग कर रूट विंडो से पूछ सकते हैं। क्लाइंट विंडोज़ की यह रिटर्न सूची विंडो प्रबंधक प्रबंधन कर रही है। अधिक जानकारी के लिए, here देखें।

हालांकि, इसके साथ कुछ समस्याएं हैं। शुरुआत के लिए, उपयोग में विंडो प्रबंधक को EWMH का समर्थन करना चाहिए। केडीई और गनोम करते हैं, और मुझे यकीन है कि कुछ अन्य भी करते हैं। हालांकि, मुझे यकीन है कि ऐसे कई हैं जो नहीं करते हैं। इसके अलावा, मैंने केडीई के साथ कुछ मुद्दों पर ध्यान दिया है। असल में, कुछ गैर-केडीई अनुप्रयोग सूची में शामिल नहीं होते हैं। उदाहरण के लिए, यदि आप केडीई के तहत xcalc चलाते हैं तो यह इस सूची में दिखाई नहीं देगा।

यदि कोई इस विधि पर कोई सुधार प्रदान कर सकता है, तो मुझे उन्हें सुनकर खुशी होगी। संदर्भ के लिए, कोड मैं उपयोग कर रहा हूँ नीचे सूचीबद्ध है:

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); 
    } 
+0

इस कोड सही नहीं है, 32 बिट प्रारूप सर्वर पर प्रयुक्त बिट्स की संख्या को संदर्भित करता है, क्लाइंट नहीं। ग्राहक हमेशा XID मानों का प्रतिनिधित्व करने के लिए 'लंबा' का उपयोग करते हैं। आपकी सरणी quint32 नहीं 'long' की सरणी होनी चाहिए। –

1

यदि आपको XlK का उपयोग करने की आवश्यकता नहीं है, तो GDK के gdk_screen_get_window_stack() और gdk_window_get_window_type() का उपयोग करके आपकी आवश्यकताओं के लिए आपकी सहायता कर सकते हैं।

6

पिछले समाधान पर विस्तार करने के लिए, आप तो खिड़की नाम प्राप्त करना चाहते हैं:

// 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); 
+0

यूप, जानकारी के लिए धन्यवाद। – Thomi

+0

ध्यान दें कि 'XFetchName' सफल हो सकता है लेकिन' name = NULL 'सेट करें। आपका उदाहरण इस मामले में दुर्घटनाग्रस्त हो जाएगा। इसके अलावा 'char * name = '\ 0'; 'भ्रामक है, निरंतर' न्यूल 'की तरह दिखना चाहिए, क्योंकि यह एक सूचक नहीं है। – Ruslan

+0

एक पूर्ण नाम को संभालने के लिए फिक्स्ड कोड। – Ben

संबंधित मुद्दे