diff options
Diffstat (limited to 'pugl')
-rw-r--r-- | pugl/detail/mac.h | 1 | ||||
-rw-r--r-- | pugl/detail/mac.m | 34 | ||||
-rw-r--r-- | pugl/detail/win.c | 14 | ||||
-rw-r--r-- | pugl/detail/x11.c | 26 | ||||
-rw-r--r-- | pugl/pugl.h | 20 |
5 files changed, 79 insertions, 16 deletions
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 <X11/Xutil.h> #include <X11/keysym.h> +#include <sys/select.h> #include <sys/time.h> #include <stdbool.h> @@ -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; } diff --git a/pugl/pugl.h b/pugl/pugl.h index e7c7333..923d361 100644 --- a/pugl/pugl.h +++ b/pugl/pugl.h @@ -88,6 +88,8 @@ typedef void* PuglHandle; */ typedef enum { PUGL_SUCCESS, + PUGL_FAILURE, + PUGL_ERR_UNKNOWN, PUGL_ERR_CREATE_WINDOW, PUGL_ERR_SET_FORMAT, PUGL_ERR_CREATE_CONTEXT, @@ -456,6 +458,20 @@ PUGL_API double puglGetTime(const PuglWorld* world); /** + Poll for events that are ready to be processed. + + This polls for events that are ready for any view in the application, + potentially blocking depending on `timeout`. + + @param world The world for all the views to poll. + @param timeout Maximum time to wait, in seconds. If zero, the call returns + immediately, if negative, the call blocks indefinitely. + @return PUGL_SUCCESS if events are read, PUGL_FAILURE if not, or an error. +*/ +PUGL_API PuglStatus +puglPollEvents(PuglWorld* world, double timeout); + +/** @} @name Initialization Configuration functions which must be called before creating a window. @@ -728,8 +744,10 @@ puglRequestAttention(PuglView* view); necessary. This function will block indefinitely if no events are available, so is not appropriate for use in programs that need to perform regular updates (e.g. animation). + + @deprecated Use puglPollEvents(). */ -PUGL_API PuglStatus +PUGL_API PUGL_DEPRECATED_BY("puglPollEvents") PuglStatus puglWaitForEvent(PuglView* view); /** |