From 93f4920cfc03d1a2a8c0df9c6d863cdf20c6ab32 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 22 Jul 2019 16:53:02 +0200 Subject: Add puglDispatchEvents() --- pugl/detail/mac.m | 20 +++++++---- pugl/detail/win.c | 12 +++++-- pugl/detail/x11.c | 106 ++++++++++++++++++++++++++++++++++-------------------- pugl/detail/x11.h | 2 ++ 4 files changed, 91 insertions(+), 49 deletions(-) (limited to 'pugl/detail') diff --git a/pugl/detail/mac.m b/pugl/detail/mac.m index 74b207a..3fa700e 100644 --- a/pugl/detail/mac.m +++ b/pugl/detail/mac.m @@ -842,20 +842,26 @@ puglWaitForEvent(PuglView* view) return puglPollEvents(view->world, -1.0); } -PuglStatus -puglProcessEvents(PuglView* view) +PUGL_API PuglStatus +puglDispatchEvents(PuglWorld* world) { for (NSEvent* ev = NULL; - (ev = [view->impl->window nextEventMatchingMask:NSAnyEventMask - untilDate:nil - inMode:NSDefaultRunLoopMode - dequeue:YES]);) { - [view->world->impl->app sendEvent: ev]; + (ev = [world->impl->app nextEventMatchingMask:NSAnyEventMask + untilDate:nil + inMode:NSDefaultRunLoopMode + dequeue:YES]);) { + [world->impl->app sendEvent: ev]; } return PUGL_SUCCESS; } +PuglStatus +puglProcessEvents(PuglView* view) +{ + return puglDispatchEvents(view->world); +} + PuglGlFunc puglGetProcAddress(const char *name) { diff --git a/pugl/detail/win.c b/pugl/detail/win.c index 9d0d0e5..6cd34e3 100644 --- a/pugl/detail/win.c +++ b/pugl/detail/win.c @@ -682,11 +682,11 @@ puglWaitForEvent(PuglView* PUGL_UNUSED(view)) return PUGL_SUCCESS; } -PuglStatus -puglProcessEvents(PuglView* view) +PUGL_API PuglStatus +puglDispatchEvents(PuglWorld* PUGL_UNUSED(world)) { MSG msg; - while (PeekMessage(&msg, view->impl->hwnd, 0, 0, PM_REMOVE)) { + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } @@ -694,6 +694,12 @@ puglProcessEvents(PuglView* view) return PUGL_SUCCESS; } +PuglStatus +puglProcessEvents(PuglView* view) +{ + return puglDispatchEvents(view->world); +} + LRESULT CALLBACK wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { diff --git a/pugl/detail/x11.c b/pugl/detail/x11.c index 7ef3866..b564225 100644 --- a/pugl/detail/x11.c +++ b/pugl/detail/x11.c @@ -127,6 +127,18 @@ puglPollEvents(PuglWorld* world, const double timeout) return ret < 0 ? PUGL_ERR_UNKNOWN : ret == 0 ? PUGL_FAILURE : PUGL_SUCCESS; } +static PuglView* +puglFindView(PuglWorld* world, const Window window) +{ + for (size_t i = 0; i < world->numViews; ++i) { + if (world->views[i]->impl->win == window) { + return world->views[i]; + } + } + + return NULL; +} + int puglCreateWindow(PuglView* view, const char* title) { @@ -557,30 +569,32 @@ merge_expose_events(PuglEvent* dst, const PuglEvent* src) } } -PuglStatus -puglProcessEvents(PuglView* view) +PUGL_API PuglStatus +puglDispatchEvents(PuglWorld* world) { - /* Maintain a single expose/configure event to execute after all pending - events. This avoids redundant drawing/configuration which prevents a - series of window resizes in the same loop from being laggy. */ - PuglInternals* const impl = view->impl; - PuglEvent expose_event = { 0 }; - PuglEvent config_event = { 0 }; - XEvent xevent; - while (XPending(impl->display) > 0) { - XNextEvent(impl->display, &xevent); - if (xevent.type == KeyRelease) { - // Ignore key repeat if necessary - if (view->hints[PUGL_IGNORE_KEY_REPEAT] && - XEventsQueued(impl->display, QueuedAfterReading)) { - XEvent next; - XPeekEvent(impl->display, &next); - if (next.type == KeyPress && - next.xkey.time == xevent.xkey.time && - next.xkey.keycode == xevent.xkey.keycode) { - XNextEvent(impl->display, &xevent); - continue; - } + // Flush just once at the start to fill event queue + Display* display = world->impl->display; + XFlush(display); + + // Process all queued events (locally, without flushing or reading) + while (XEventsQueued(display, QueuedAlready) > 0) { + XEvent xevent; + XNextEvent(display, &xevent); + + PuglView* view = puglFindView(world, xevent.xany.window); + if (!view) { + continue; + } + + // Handle special events + PuglInternals* const impl = view->impl; + if (xevent.type == KeyRelease && view->hints[PUGL_IGNORE_KEY_REPEAT]) { + XEvent next; + if (XCheckTypedWindowEvent(display, impl->win, KeyPress, &next) && + next.type == KeyPress && + next.xkey.time == xevent.xkey.time && + next.xkey.keycode == xevent.xkey.keycode) { + continue; } } else if (xevent.type == FocusIn) { XSetICFocus(impl->xic); @@ -593,38 +607,52 @@ puglProcessEvents(PuglView* view) if (event.type == PUGL_EXPOSE) { // Expand expose event to be dispatched after loop - merge_expose_events(&expose_event, &event); + merge_expose_events(&view->impl->pendingExpose, &event); } else if (event.type == PUGL_CONFIGURE) { // Expand configure event to be dispatched after loop - config_event = event; + view->impl->pendingConfigure = event; } else { // Dispatch event to application immediately puglDispatchEvent(view, &event); } } - if (config_event.type || expose_event.type) { - const bool draw = expose_event.type && expose_event.expose.count == 0; - - puglEnterContext(view, draw); + // Flush pending configure and expose events for all views + for (size_t i = 0; i < world->numViews; ++i) { + PuglView* const view = world->views[i]; + PuglEvent* const configure = &view->impl->pendingConfigure; + PuglEvent* const expose = &view->impl->pendingExpose; + + if (configure->type || expose->type) { + const bool mustExpose = expose->type && expose->expose.count == 0; + puglEnterContext(view, mustExpose); + + if (configure->type) { + view->width = (int)configure->configure.width; + view->height = (int)configure->configure.height; + view->backend->resize(view, view->width, view->height); + view->eventFunc(view, &view->impl->pendingConfigure); + } - if (config_event.type) { - view->width = (int)config_event.configure.width; - view->height = (int)config_event.configure.height; - view->backend->resize(view, view->width, view->height); - view->eventFunc(view, (const PuglEvent*)&config_event); - } + if (mustExpose) { + view->eventFunc(view, &view->impl->pendingExpose); + } - if (draw) { - view->eventFunc(view, (const PuglEvent*)&expose_event); + puglLeaveContext(view, mustExpose); + configure->type = 0; + expose->type = 0; } - - puglLeaveContext(view, draw); } return PUGL_SUCCESS; } +PuglStatus +puglProcessEvents(PuglView* view) +{ + return puglDispatchEvents(view->world); +} + double puglGetTime(const PuglWorld* world) { diff --git a/pugl/detail/x11.h b/pugl/detail/x11.h index 34694fe..be5f3e0 100644 --- a/pugl/detail/x11.h +++ b/pugl/detail/x11.h @@ -45,4 +45,6 @@ struct PuglInternalsImpl { Window win; XIC xic; PuglSurface* surface; + PuglEvent pendingConfigure; + PuglEvent pendingExpose; }; -- cgit v1.2.1