aboutsummaryrefslogtreecommitdiffstats
path: root/pugl/detail
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2019-07-22 16:53:02 +0200
committerDavid Robillard <d@drobilla.net>2019-09-03 08:32:16 +0200
commit93f4920cfc03d1a2a8c0df9c6d863cdf20c6ab32 (patch)
tree64ef7427a32b88183bae8720b07fc9258b769b3e /pugl/detail
parent496f17c3804c79d304aa6095b92768593d1cc700 (diff)
downloadpugl-93f4920cfc03d1a2a8c0df9c6d863cdf20c6ab32.tar.gz
pugl-93f4920cfc03d1a2a8c0df9c6d863cdf20c6ab32.tar.bz2
pugl-93f4920cfc03d1a2a8c0df9c6d863cdf20c6ab32.zip
Add puglDispatchEvents()
Diffstat (limited to 'pugl/detail')
-rw-r--r--pugl/detail/mac.m20
-rw-r--r--pugl/detail/win.c12
-rw-r--r--pugl/detail/x11.c106
-rw-r--r--pugl/detail/x11.h2
4 files changed, 91 insertions, 49 deletions
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;
};