@@ -267,6 +267,10 @@ int spnav_fd(void)
267267 return sock ;
268268}
269269
270+
271+ /* Checks both the event queue and the daemon socket for pending events.
272+ * In either case, it returns immediately with true/false values (doesn't block).
273+ */
270274static int event_pending (int s )
271275{
272276 fd_set rd_set ;
@@ -288,6 +292,10 @@ static int event_pending(int s)
288292 return 0 ;
289293}
290294
295+ /* If there are events waiting in the event queue, dequeue one and
296+ * return that, otherwise read one from the daemon socket.
297+ * This might block unless we called event_pending() first and it returned true.
298+ */
291299static int read_event (int s , spnav_event * event )
292300{
293301 int i , rd ;
@@ -298,6 +306,11 @@ static int read_event(int s, spnav_event *event)
298306 struct event_node * node = ev_queue -> next ;
299307 ev_queue -> next = ev_queue -> next -> next ;
300308
309+ /* dequeued the last event, must update tail pointer */
310+ if (ev_queue_tail == node ) {
311+ ev_queue_tail = ev_queue ;
312+ }
313+
301314 memcpy (event , & node -> event , sizeof * event );
302315 free (node );
303316 return event -> type ;
@@ -399,18 +412,26 @@ static Bool match_events(Display *dpy, XEvent *xev, char *arg)
399412}
400413#endif
401414
402- static int enqueue_event (spnav_event * event )
415+ /* Appends an event to an event list.
416+ * Tailptr must be a pointer to the tail pointer of the list. NULL means
417+ * append to the global event queue.
418+ */
419+ static int enqueue_event (spnav_event * event , struct event_node * * tailptr )
403420{
404421 struct event_node * node ;
405422 if (!(node = malloc (sizeof * node ))) {
406423 return -1 ;
407424 }
408425
409- memcpy ( & node -> event , event , sizeof node -> event ) ;
426+ node -> event = * event ;
410427 node -> next = 0 ;
428+
429+ if (!tailptr ) {
430+ tailptr = & ev_queue_tail ;
431+ }
411432
412- ev_queue_tail -> next = node ;
413- ev_queue_tail = node ;
433+ ( * tailptr ) -> next = node ;
434+ * tailptr = node ;
414435 return 0 ;
415436}
416437
@@ -430,16 +451,38 @@ int spnav_remove_events(int type)
430451#endif
431452
432453 if (sock ) {
454+ struct event_node * tmplist , * tmptail ;
455+
456+ if (!(tmplist = tmptail = malloc (sizeof * tmplist ))) {
457+ return -1 ;
458+ }
459+ tmplist -> next = 0 ;
460+
461+ /* while there are events in the event queue, or the daemon socket */
433462 while (event_pending (sock )) {
434463 spnav_event event ;
435464
436- read_event (sock , & event );
465+ read_event (sock , & event ); /* remove next event */
437466 if (event .type != type ) {
438- enqueue_event (& event );
467+ /* We don't want to drop this one, wrong type. Keep the event
468+ * in the temporary list, for deferred reinsertion
469+ */
470+ enqueue_event (& event , & tmptail );
439471 } else {
440472 rm_count ++ ;
441473 }
442474 }
475+
476+ /* reinsert any events we removed that we didn't mean to */
477+ while (tmplist -> next ) {
478+ struct event_node * node = tmplist -> next ;
479+
480+ enqueue_event (& node -> event , 0 );
481+
482+ free (tmplist );
483+ tmplist = node ;
484+ }
485+
443486 return rm_count ;
444487 }
445488 return 0 ;
0 commit comments