c - मैं X11 ईवेंट लूप से इनायत कैसे करूं?




linux xlib (2)

एक्स 11 में "एक्जिट बटन" या "एप्लिकेशन" या "क्लोज इवेंट" जैसी चीजें नहीं हैं। यह डिजाइन द्वारा है।

खिड़की की सजावट, बाहर निकलने के बटन और कई अन्य चीजें जिन पर हम निर्भर करते हैं, वे X11 में नहीं बने हैं। वे इसके बजाय कोर X11 के शीर्ष पर कार्यान्वित किए जाते हैं। wmDeleteMessage के लिए जिम्मेदार सम्मेलनों के विशेष सेट का नाम wmDeleteMessage है, इसे देखिए।

Xlib केवल कोर X11 प्रोटोकॉल से संबंधित है। कोई अंतर्निहित घटना नहीं है।

ऐसे टूलकिट हैं जो ICCCM और अन्य सभी चीजों के साथ काम कर रहे हैं जो X11 आसान (GTK, wxWindows, Qt, ...) में नहीं बने हैं, आप शायद उनमें से किसी एक का उपयोग करना चाहते हैं।

मुझे मिलने वाला लगभग हर ट्यूटोरियल मुझे अपने इवेंट लूप के लिए ऐसा करने के लिए कहता है:

XEvent event;

while (true)
{
    XNextEvent(display, &event);

    switch (event.type)
    {
        case Expose:
            printf("Expose\n");
            break;

        default:
            break;
    }
}

हालाँकि, इस संदेश में प्रोग्राम परिणाम को बंद करने के लिए X पर क्लिक करने से।

XIO:  fatal IO error 11 (Resource temporarily unavailable) on X server ":0"
after 10 requests (10 known processed) with 0 events remaining.

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

Atom wmDeleteMessage = XInternAtom(mDisplay, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, window, &wmDeleteMessage, 1);

XEvent event;
bool running = true;

while (running)
{
    XNextEvent(display, &event);

    switch (event.type)
    {
        case Expose:
            printf("Expose\n");
            break;

        case ClientMessage:
            if (event.xclient.data.l[0] == wmDeleteMessage)
                running = false;
            break;

        default:
            break;
    }
}

यह काम करता है। यह त्रुटियों के बिना बाहर निकलता है। ... लेकिन मैं यह मानने से इनकार करता हूं कि यह चीजें करने का सामान्य तरीका है। मेरा मतलब है, यह एक X11 ऐप को ठीक से बाहर निकालने का एकमात्र तरीका है? यह सिर्फ करीबी घटना को पकड़ने के लिए बहुत काम की तरह लगता है। मैं 'उचित' इवेंट लूप कैसे बनाऊं? करीबी घटना इतनी गहराई से दफन क्यों है? मैं क्या खो रहा हूँ?


समस्या X सर्वर और विंडो प्रबंधक के बीच संचार में रहती है।

जब आप XCreateWindow या XCreateSimpleWindow , तो X सर्वर आपकी विंडो बनाता है (इसे तब तक नहीं दिखाता जब तक कि आप स्पष्ट रूप से XMapWindow कॉल करके इसे स्क्रीन पर मैप XMapWindow ), और फिर विंडो प्रबंधक आपकी विंडो के चारों ओर की सभी सजावट और बटन और सिस्टम मेनू को संलग्न करने के लिए जिम्मेदार होता है। ।

आप विंडो को हटाने के लिए अपने दम पर XDestroyWindow को कॉल कर सकते हैं, और इसका मतलब आमतौर पर यह सिर्फ स्क्रीन से गायब हो जाता है, लेकिन आपका प्रोग्राम अभी भी चल रहा है और एक्स सर्वर से कनेक्शन अभी भी खुला है, इसलिए आप इसे कुछ और अनुरोध भेज सकते हैं।

समस्या तब शुरू होती है जब उपयोगकर्ता विंडो प्रबंधक द्वारा आपकी विंडो से जुड़ी उस छोटी सी एक्स बटन पर क्लिक करता है, क्योंकि यह एक्स सर्वर द्वारा नहीं बनाया गया है और फिर यह तय करना उसका व्यवसाय नहीं है। अब यह सब विंडो मैनेजर के हाथ में है।

यदि विंडो मैनेजर ने बस आपकी विंडो पर XDestroyWindow को XDestroyWindow किया है, तो यह एक समस्या का कारण होगा यदि आपका एप्लिकेशन विंडो को नष्ट होने से पहले कुछ करने के लिए समापन घटना को कैप्चर करना चाहता था। तो इस प्रक्रिया को संभालने के लिए X सर्वर और विंडो मैनेजरों के बीच सम्मेलन स्थापित किया गया है।

अधिकांश विंडो मैनेजरों का डिफ़ॉल्ट व्यवहार विंडो को नष्ट करने और एक्स सर्वर के साथ कनेक्शन को बंद करने के लिए है , क्योंकि विंडो मैनेजरों के अधिकांश उपयोगकर्ता यही अपेक्षा करते हैं: जब वे विंडो को बंद करेंगे, तो कार्यक्रम समाप्त हो जाएगा (और कनेक्शन) X सर्वर बंद विंडो के साथ बंद हो जाएगा)। और फिर, जब आप XCloseDisplay(display) को कॉल करने का प्रयास करते हैं, तो यह आपके द्वारा उल्लिखित IO त्रुटि का कारण होगा, क्योंकि सर्वर से कनेक्शन पहले से ही बंद है और display संरचना अमान्य है।

यहाँ Xlib प्रलेखन से एक अंश है जो यह बताता है:

WM_PROTOCOLS संपत्ति में WM_DELETE_WINDOW को शामिल नहीं करने का चयन करने वाले ग्राहक सर्वर से डिस्कनेक्ट हो सकते हैं यदि उपयोगकर्ता क्लाइंट के शीर्ष स्तर की खिड़कियों में से एक को हटाने के लिए कहता है।

हाँ, यह बहुत अच्छा होगा यदि वे इसे अपने डॉक्स में इतना गहरा नहीं छिपाते हैं, हालांकि: -पी लेकिन जब आप पहले से ही इसे पा लेते हैं, तो सौभाग्य से यह समाधान के लिए संकेत भी देता है।

यदि आप एक अलग व्यवहार चाहते हैं (अर्थात विंडो मैनेजर से समापन घटना को पकड़ने के लिए), तो आपको WM_DESTROY_WINDOW प्रोटोकॉल का उपयोग करने की WM_DESTROY_WINDOW है।

डॉक्स से एक और अंश:

ग्राहक, आमतौर पर उन कई शीर्ष-स्तरीय खिड़कियों वाले, जिनके सर्वर कनेक्शन को उनकी शीर्ष-स्तरीय खिड़कियों में से कुछ को हटाने से बचना चाहिए, प्रत्येक विंडो पर WM_PROTOCOLS गुण में atom WM_DELETE_WINDOW को शामिल करना चाहिए। जैसा कि ऊपर वर्णित data[0] फ़ील्ड ClientMessage उन्हें एक ClientMessage ईवेंट प्राप्त होगा।

मेरे पास एक ही त्रुटि थी और मैं जानना चाहता था कि वास्तव में इसके क्या कारण हैं और क्यों। मुझे यह पता लगाने और डॉक्टर में उचित स्पष्टीकरण खोजने में कुछ समय लगा, इसलिए मैंने दूसरों के समय को बेहतर बनाने के लिए अपनी व्याख्या को यहां रखा।





xlib