comment quitter le blocage de XNextEvent de xlib

Sous Windows, le thread d’interface graphique appelle généralement GetMessage pour attendre un message. Lorsqu’un autre thread utilise PoseMessage pour mettre un message dans la queue, le thread d’interface graphique renverra GetMessage (blocage bloquant).

Quelqu’un peut-il me dire, lorsque j’utilise XNextEvent sous XWindows pour attendre un événement, comment puis-je “réveiller” le fil de l’interface graphique dans un autre fil. Existe-t-il des API comme PoseMessage que je peux utiliser?

C’est pourquoi la plupart des infrastructures d’interface utilisateur (Gtk, KDE, etc.) utilisent des boucles principales personnalisées pour pouvoir écouter davantage de sources d’événements.

En interne, XNextEvent utilise un socket et appelle donc select() pour savoir quand une entrée est disponible. Vous pouvez donc: Appeler ConnectionNumber(display) pour obtenir le descripteur de fichier que vous devez transmettre à select()

Cela vous permet d’écouter plusieurs descripteurs de fichier.

Exemple de code provenant de http://www.linuxquestions.org/questions/showthread.php?p=2431345#post2431345

 #include  #include  #include  #include  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); } 

Vous pouvez quitter le blocage XNextEvent en vous envoyant un événement factice.

 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); ... } 

Dans un autre fil, vous pouvez faire ceci pour terminer la boucle:

 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); 

Vous devez utiliser: Bool XCheckMaskEvent (Display *, long, XEvent)

La fonction XCheckMaskEvent recherche d’abord le premier événement correspondant au masque spécifié dans la queue des événements, puis dans tous les événements disponibles sur la connexion au serveur.

S’il trouve une correspondance, XCheckMaskEvent supprime cet événement, le copie dans la structure XEvent spécifiée et renvoie True . Les autres événements stockés dans la queue ne sont pas ignorés.

Si l’événement que vous avez demandé n’est pas disponible, XCheckMaskEvent renvoie False et le tampon de sortie a été vidé.