From 496f17c3804c79d304aa6095b92768593d1cc700 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 22 Jul 2019 16:53:36 +0200 Subject: Add puglPollEvents() This allows waiting for events for any view in the world. It also improves on puglWaitForEvent() by the addition of a time parameter that allows indefinite blocking, non-blocking polling, and blocking polling with a timeout. --- pugl/detail/mac.h | 1 - pugl/detail/mac.m | 34 ++++++++++++++++++++-------------- pugl/detail/win.c | 14 ++++++++++++++ pugl/detail/x11.c | 26 ++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 15 deletions(-) (limited to 'pugl/detail') diff --git a/pugl/detail/mac.h b/pugl/detail/mac.h index f8cfbed..1bd2bbc 100644 --- a/pugl/detail/mac.h +++ b/pugl/detail/mac.h @@ -60,6 +60,5 @@ struct PuglInternalsImpl { PuglWrapperView* wrapperView; NSView* drawView; id window; - NSEvent* nextEvent; uint32_t mods; }; diff --git a/pugl/detail/mac.m b/pugl/detail/mac.m index 527724d..74b207a 100644 --- a/pugl/detail/mac.m +++ b/pugl/detail/mac.m @@ -816,29 +816,35 @@ puglRequestAttention(PuglView* view) } PuglStatus -puglWaitForEvent(PuglView* view) +puglPollEvents(PuglWorld* world, const double timeout) { + NSDate* date = ((timeout < 0) ? [NSDate distantFuture] : + (timeout == 0) ? nil : + [NSDate dateWithTimeIntervalSinceNow:timeout]); + /* Note that dequeue:NO is broken (it blocks forever even when events are - pending), so we work around this by dequeueing the event here and - storing it in view->impl->nextEvent for later processing. */ - if (!view->impl->nextEvent) { - view->impl->nextEvent = - [view->impl->window nextEventMatchingMask:NSAnyEventMask]; - } + pending), so we work around this by dequeueing the event then posting it + back to the front of the queue. */ + NSEvent* event = [world->impl->app + nextEventMatchingMask:NSAnyEventMask + untilDate:date + inMode:NSDefaultRunLoopMode + dequeue:YES]; + + [world->impl->app postEvent:event atStart:true]; return PUGL_SUCCESS; } PuglStatus -puglProcessEvents(PuglView* view) +puglWaitForEvent(PuglView* view) { - if (view->impl->nextEvent) { - // Process event that was dequeued earier by puglWaitForEvent - [view->world->impl->app sendEvent: view->impl->nextEvent]; - view->impl->nextEvent = NULL; - } + return puglPollEvents(view->world, -1.0); +} - // Process all pending events +PuglStatus +puglProcessEvents(PuglView* view) +{ for (NSEvent* ev = NULL; (ev = [view->impl->window nextEventMatchingMask:NSAnyEventMask untilDate:nil diff --git a/pugl/detail/win.c b/pugl/detail/win.c index 6a0825a..9d0d0e5 100644 --- a/pugl/detail/win.c +++ b/pugl/detail/win.c @@ -120,6 +120,20 @@ puglInitViewInternals(void) return (PuglInternals*)calloc(1, sizeof(PuglInternals)); } +PuglStatus +puglPollEvents(PuglWorld* world, const double timeout) +{ + (void)world; + + if (timeout < 0) { + WaitMessage(); + } else { + MsgWaitForMultipleObjects( + 0, NULL, FALSE, (DWORD)(timeout * 1e3), QS_ALLEVENTS); + } + return PUGL_SUCCESS; +} + int puglCreateWindow(PuglView* view, const char* title) { diff --git a/pugl/detail/x11.c b/pugl/detail/x11.c index d54f1bf..7ef3866 100644 --- a/pugl/detail/x11.c +++ b/pugl/detail/x11.c @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -102,6 +103,30 @@ puglInitViewInternals(void) return (PuglInternals*)calloc(1, sizeof(PuglInternals)); } +PuglStatus +puglPollEvents(PuglWorld* world, const double timeout) +{ + XFlush(world->impl->display); + + const int fd = ConnectionNumber(world->impl->display); + const int nfds = fd + 1; + int ret = 0; + fd_set fds; + FD_ZERO(&fds); + FD_SET(fd, &fds); + + if (timeout < 0.0) { + ret = select(nfds, &fds, NULL, NULL, NULL); + } else { + const long sec = (long)timeout; + const long msec = (long)((timeout - (double)sec) * 1e6); + struct timeval tv = {sec, msec}; + ret = select(nfds, &fds, NULL, NULL, &tv); + } + + return ret < 0 ? PUGL_ERR_UNKNOWN : ret == 0 ? PUGL_FAILURE : PUGL_SUCCESS; +} + int puglCreateWindow(PuglView* view, const char* title) { @@ -193,6 +218,7 @@ void puglShowWindow(PuglView* view) { XMapRaised(view->impl->display, view->impl->win); + puglPostRedisplay(view); view->visible = true; } -- cgit v1.2.1