2011-12-21 17 views
22

खिड़कियों के तहत, जीयूआई धागा आमतौर पर संदेश, के लिए इंतजार करने के लिए GetMessage फोन जब एक और धागा उपयोग PoseMessage कतार में संदेश डाल छोड़ने की, तो जीयूआई धागा लौट GetMessage (अवरुद्ध छोड़ने) होगा ।कैसे Xlib के XNextEvent को अवरुद्ध

क्या कोई मुझे बता सकता है, जब मैं XWextEvent के तहत XVextEvent का उपयोग ईवेंट की प्रतीक्षा करने के लिए करता हूं, तो मैं एक और थ्रेड में जीयूआई थ्रेड को "जागृत" कैसे कर सकता हूं। क्या एपीआई जैसे PoseMessage I का उपयोग कर सकते हैं?

उत्तर

35

नहीं। यही कारण है कि अधिकांश यूआई ढांचे (जीटीके, केडीई, आदि) कस्टम मुख्य लूप का उपयोग अधिक घटना स्रोतों को सुनने में सक्षम होने के लिए करते हैं।

आंतरिक रूप से, XNextEvent सॉकेट का उपयोग करता है, इसलिए इनपुट उपलब्ध होने पर यह जानने के लिए select() पर कॉल किया जाता है। तो आप: ConnectionNumber(display) पर फ़ाइल डिस्क्रिप्टर को प्राप्त करने के लिए कॉल करें जिसे आपको select()

आपको कई फ़ाइल डिस्क्रिप्टर सुनने की अनुमति देता है।

नमूना कोड http://www.linuxquestions.org/questions/showthread.php?p=2431345#post2431345

#include <stdio.h> 
#include <stdlib.h> 
#include <X11/Xlib.h> 
#include <X11/Xutil.h> 

Display *dis; 
Window win; 
int x11_fd; 
fd_set in_fds; 

struct timeval tv; 
XEvent ev; 

int main() { 
    dis = XOpenDisplay(NULL); 
    win = XCreateSimpleWindow(dis, RootWindow(dis, 0), 1, 1, 256, 256, \ 
     0, BlackPixel (dis, 0), BlackPixel(dis, 0)); 

    // You don't need all of these. Make the mask as you normally would. 
    XSelectInput(dis, win, 
     ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | 
     ButtonPressMask | ButtonReleaseMask | StructureNotifyMask 
     ); 

    XMapWindow(dis, win); 
    XFlush(dis); 

    // This returns the FD of the X11 display (or something like that) 
    x11_fd = ConnectionNumber(dis); 

    // Main loop 
    while(1) { 
     // Create a File Description Set containing x11_fd 
     FD_ZERO(&in_fds); 
     FD_SET(x11_fd, &in_fds); 

     // Set our timer. One second sounds good. 
     tv.tv_usec = 0; 
     tv.tv_sec = 1; 

     // Wait for X Event or a Timer 
     int num_ready_fds = select(x11_fd + 1, &in_fds, NULL, NULL, &tv); 
     if (num_ready_fds > 0) 
      printf("Event Received!\n"); 
     else if (num_ready_fds == 0) 
      // Handle timer here 
      printf("Timer Fired!\n"); 
     else 
      printf("An error occured!\n"); 

     // Handle XEvents and flush the input 
     while(XPending(dis)) 
      XNextEvent(dis, &ev); 
    } 
    return(0); 
} 
+0

हाय हारून यह एक शानदार समाधान है। यह केवल उस खिड़की में घटनाओं को पकड़ रहा है, क्या वैश्विक स्तर पर माउस घटनाओं को सुनना संभव है? और इस विधि के साथ माउस घटनाओं को ब्लॉक करने के लिए संभव है? – Noitidart

+1

@ नोइटिडार्ट: शायद लेकिन मैं उस टिप्पणी में इसका उत्तर नहीं दे सकता। एक नया प्रश्न पूछें, कृपया और अधिक जानकारी देने के लिए मत भूलना कि आपको वास्तव में क्या हासिल करने की आवश्यकता है। –

+0

आह धन्यवाद, मैंने यहां प्रश्न पोस्ट किया है: http://stackoverflow.com/questions/32262767/mouse-events-callback – Noitidart

9

से आप अवरुद्ध XNextEvent छोड़ सकते अपने आप को एक डमी घटना भेजकर,।

Window interClientCommunicationWindow; 
Bool x11EventLoopActive = True; 

// create a dummy window, that we can use to end the blocking XNextEvent call 
interClientCommunicationWindow = XCreateSimpleWindow(dpy, root, 10, 10, 10, 10, 0, 0, 0); 
XSelectInput(dpy, interClientCommunicationWindow, StructureNotifyMask); 

XEvent event; 
while(x11EventLoopActive) { 
    XNextEvent(dpy, &event); 
    ... 
} 

एक और धागा आप पाश समाप्त करने के लिए यह कर सकते हैं:

x11EventLoopActive = False; 
// push a dummy event into the queue so that the event loop has a chance to stop 
XClientMessageEvent dummyEvent; 
memset(&dummyEvent, 0, sizeof(XClientMessageEvent)); 
dummyEvent.type = ClientMessage; 
dummyEvent.window = interClientCommunicationWindow; 
dummyEvent.format = 32; 
XSendEvent(dpy, interClientCommunicationWindow, 0, 0, (XEvent*)&dummyEvent); 
XFlush(dpy); 
+8

खतरे, विल रॉबिन्सन! Xlib * थ्रेड सुरक्षित नहीं है *! उपर्युक्त कोड ऐसा प्रतीत होता है जैसे यह काम करता है, लेकिन वास्तव में एक बहुत ही कठिन-से-डीबग तरीके से यादृच्छिक रूप से और अकसर क्रैश होगा। ऐसा मत करो! –

+1

@DavidGiven क्या होगा यदि हम 'XInitThreads' कहलाते हैं? – Noitidart

2

आप उपयोग करना चाहिए: बूल XCheckMaskEvent (प्रदर्शन *, लंबे, XEvent)

XCheckMaskEvent समारोह पहले खोजें इवेंट कतार, और फिर निर्दिष्ट मास्क से मेल खाने वाली पहली घटना के लिए सर्वर कनेक्शन पर उपलब्ध कोई भी ईवेंट।

यह एक मैच मिलता है, तो XCheckMaskEvent, उस घटना को हटा यह प्रतियां निर्दिष्ट XEvent संरचना में, और True देता है। कतार में संग्रहीत अन्य घटनाओं को त्याग दिया नहीं जाता है।

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

+0

मैं इसे काम नहीं कर सका। मैं पॉइंटरबैरियर घटनाओं की प्रतीक्षा कर रहा था, और यह सुनिश्चित नहीं किया कि मास्क उचित होगा? क्या काम किया गया था, अगर (XPing (_display)> 0) का उपयोग कर रहा था; फिर XNextEvent; और जारी रखें; – kevinf

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