@@ -30,8 +30,10 @@ OF SUCH DAMAGE.
3030#include <errno.h>
3131#include <unistd.h>
3232#include <sys/types.h>
33+ #include <sys/time.h>
3334#include <sys/socket.h>
3435#include <sys/un.h>
36+ #include <sys/select.h>
3537#include "spnav.h"
3638
3739#ifdef USE_X11
@@ -55,8 +57,17 @@ enum {
5557#define IS_OPEN (sock)
5658#endif
5759
60+ struct event_node {
61+ spnav_event event ;
62+ struct event_node * next ;
63+ };
64+
65+ /* only used for non-X mode, with spnav_remove_events */
66+ static struct event_node * ev_queue , * ev_queue_tail ;
67+
5868static int sock ;
5969
70+
6071int spnav_open (void )
6172{
6273 int s ;
@@ -66,7 +77,12 @@ int spnav_open(void)
6677 return -1 ;
6778 }
6879
69- if ((s = socket (AF_UNIX , SOCK_STREAM , 0 )) == -1 ) {
80+ if (!(ev_queue = malloc (sizeof * ev_queue ))) {
81+ return -1 ;
82+ }
83+ ev_queue_tail = ev_queue ;
84+
85+ if ((s = socket (PF_UNIX , SOCK_STREAM , 0 )) == -1 ) {
7086 return -1 ;
7187 }
7288
@@ -75,6 +91,7 @@ int spnav_open(void)
7591 strcpy (addr .sun_path , "/tmp/spacenav_usock" );
7692
7793 if (connect (s , (struct sockaddr * )& addr , sizeof addr ) == -1 ) {
94+ perror ("connect failed" );
7895 return -1 ;
7996 }
8097
@@ -118,6 +135,12 @@ int spnav_close(void)
118135 }
119136
120137 if (sock ) {
138+ while (ev_queue ) {
139+ void * tmp = ev_queue ;
140+ ev_queue = ev_queue -> next ;
141+ free (tmp );
142+ }
143+
121144 close (sock );
122145 sock = 0 ;
123146 return 0 ;
@@ -238,25 +261,90 @@ int spnav_fd(void)
238261 return sock ? sock : -1 ;
239262}
240263
264+ static int event_pending (int s )
265+ {
266+ fd_set rd_set ;
267+ struct timeval tv ;
268+
269+ if (ev_queue -> next ) {
270+ return 1 ;
271+ }
272+
273+ FD_ZERO (& rd_set );
274+ FD_SET (s , & rd_set );
275+
276+ /* don't block, just poll */
277+ tv .tv_sec = tv .tv_usec = 0 ;
278+
279+ if (select (s + 1 , & rd_set , 0 , 0 , & tv ) > 0 ) {
280+ return 1 ;
281+ }
282+ return 0 ;
283+ }
284+
285+ static int read_event (int s , spnav_event * event )
286+ {
287+ int i , rd ;
288+ int data [8 ];
289+
290+ /* if we have a queued event, deliver that one */
291+ if (ev_queue -> next ) {
292+ struct event_node * node = ev_queue -> next ;
293+ ev_queue -> next = ev_queue -> next -> next ;
294+
295+ memcpy (event , & node -> event , sizeof * event );
296+ free (node );
297+ return event -> type ;
298+ }
299+
300+ /* otherwise read one from the connection */
301+ do {
302+ rd = read (s , data , sizeof data );
303+ } while (rd == -1 && errno == EINTR );
304+
305+ if (rd == -1 ) {
306+ return 0 ;
307+ }
308+
309+ if (data [0 ] < 0 || data [0 ] > 2 ) {
310+ return 0 ;
311+ }
312+ event -> type = data [0 ] ? SPNAV_EVENT_BUTTON : SPNAV_EVENT_MOTION ;
313+
314+ if (event -> type == SPNAV_EVENT_MOTION ) {
315+ event -> motion .data = & event -> motion .x ;
316+ for (i = 0 ; i < 6 ; i ++ ) {
317+ event -> motion .data [i ] = data [i + 1 ];
318+ }
319+ event -> motion .period = data [7 ];
320+ } else {
321+ event -> button .press = data [0 ] == 1 ? 1 : 0 ;
322+ event -> button .bnum = data [1 ];
323+ }
324+
325+ return event -> type ;
326+ }
327+
241328
242329int spnav_wait_event (spnav_event * event )
243330{
244331#ifdef USE_X11
245332 if (dpy ) {
246333 for (;;) {
247- int evtype ;
248334 XEvent xev ;
249335 XNextEvent (dpy , & xev );
250336
251- if (( evtype = spnav_x11_event (& xev , event ) ) > 0 ) {
252- return evtype ;
337+ if (spnav_x11_event (& xev , event ) > 0 ) {
338+ return event -> type ;
253339 }
254340 }
255341 }
256342#endif
257343
258344 if (sock ) {
259- /* TODO implement event reception from the UNIX socket */
345+ if (read_event (sock , event ) > 0 ) {
346+ return event -> type ;
347+ }
260348 }
261349 return 0 ;
262350}
@@ -276,7 +364,11 @@ int spnav_poll_event(spnav_event *event)
276364#endif
277365
278366 if (sock ) {
279- /* TODO implement event reception from the UNIX socket */
367+ if (event_pending (sock )) {
368+ if (read_event (sock , event ) > 0 ) {
369+ return event -> type ;
370+ }
371+ }
280372 }
281373 return 0 ;
282374}
@@ -301,6 +393,21 @@ static Bool match_events(Display *dpy, XEvent *xev, char *arg)
301393}
302394#endif
303395
396+ static int enqueue_event (spnav_event * event )
397+ {
398+ struct event_node * node ;
399+ if (!(node = malloc (sizeof * node ))) {
400+ return -1 ;
401+ }
402+
403+ memcpy (& node -> event , event , sizeof node -> event );
404+ node -> next = 0 ;
405+
406+ ev_queue_tail -> next = node ;
407+ ev_queue_tail = node ;
408+ return 0 ;
409+ }
410+
304411int spnav_remove_events (int type )
305412{
306413 int rm_count = 0 ;
@@ -317,7 +424,17 @@ int spnav_remove_events(int type)
317424#endif
318425
319426 if (sock ) {
320- /* TODO */
427+ while (event_pending (sock )) {
428+ spnav_event event ;
429+
430+ read_event (sock , & event );
431+ if (event .type != type ) {
432+ enqueue_event (& event );
433+ } else {
434+ rm_count ++ ;
435+ }
436+ }
437+ return rm_count ;
321438 }
322439 return 0 ;
323440}
0 commit comments