diff options
author | David Robillard <d@drobilla.net> | 2019-11-03 19:02:38 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2019-11-03 21:03:18 +0100 |
commit | d9239872c71d117f78ce6c109cd9ab42e2d80c6b (patch) | |
tree | 7a25bbe867d750155711577deaa604a2ad722632 /pugl/detail | |
parent | d53ce364a7c7c0d9b0d1fa87077df2dff69688e9 (diff) | |
download | pugl-d9239872c71d117f78ce6c109cd9ab42e2d80c6b.tar.gz pugl-d9239872c71d117f78ce6c109cd9ab42e2d80c6b.tar.bz2 pugl-d9239872c71d117f78ce6c109cd9ab42e2d80c6b.zip |
X11: Only merge expose events if they intersect
Towards actual fine-grained exposure. This uses the previous behaviour if
expose events intersect to reduce redundant drawing, but dispatches expose
events immediately (after flushing and pending configure events) if they don't
to support partial redraws.
Diffstat (limited to 'pugl/detail')
-rw-r--r-- | pugl/detail/x11.c | 58 |
1 files changed, 45 insertions, 13 deletions
diff --git a/pugl/detail/x11.c b/pugl/detail/x11.c index e576b49..871c16b 100644 --- a/pugl/detail/x11.c +++ b/pugl/detail/x11.c @@ -586,8 +586,17 @@ puglWaitForEvent(PuglView* view) return PUGL_SUCCESS; } +static bool +exposeEventsIntersect(const PuglEvent* a, const PuglEvent* b) +{ + return !(a->expose.x + a->expose.width < b->expose.x || + b->expose.x + b->expose.width < a->expose.x || + a->expose.y + a->expose.height < b->expose.y || + b->expose.y + b->expose.height < a->expose.y); +} + static void -merge_expose_events(PuglEvent* dst, const PuglEvent* src) +mergeExposeEvents(PuglEvent* dst, const PuglEvent* src) { if (!dst->type) { *dst = *src; @@ -615,6 +624,26 @@ sendRedisplayEvent(PuglView* view) XSendEvent(view->impl->display, view->impl->win, False, 0, (XEvent*)&ev); } +static void +flushPendingConfigure(PuglView* view) +{ + PuglEvent* const configure = &view->impl->pendingConfigure; + + if (configure->type) { + view->frame.x = configure->configure.x; + view->frame.y = configure->configure.y; + view->frame.width = configure->configure.width; + view->frame.height = configure->configure.height; + + view->backend->resize(view, + (int)view->frame.width, + (int)view->frame.height); + + view->eventFunc(view, configure); + configure->type = 0; + } +} + PUGL_API PuglStatus puglDispatchEvents(PuglWorld* world) { @@ -712,7 +741,20 @@ puglDispatchEvents(PuglWorld* world) if (event.type == PUGL_EXPOSE) { // Expand expose event to be dispatched after loop - merge_expose_events(&view->impl->pendingExpose, &event); + if (view->impl->pendingConfigure.type || + (view->impl->pendingExpose.type && + exposeEventsIntersect(&view->impl->pendingExpose, &event))) { + mergeExposeEvents(&view->impl->pendingExpose, &event); + } else { + if (view->impl->pendingExpose.type) { + puglEnterContext(view, true); + flushPendingConfigure(view); + puglDispatchEvent(view, &view->impl->pendingExpose); + puglLeaveContext(view, true); + } + + view->impl->pendingExpose = event; + } } else if (event.type == PUGL_CONFIGURE) { // Expand configure event to be dispatched after loop view->impl->pendingConfigure = event; @@ -732,17 +774,7 @@ puglDispatchEvents(PuglWorld* world) const bool mustExpose = expose->type && expose->expose.count == 0; puglEnterContext(view, mustExpose); - if (configure->type) { - view->frame.x = configure->configure.x; - view->frame.y = configure->configure.y; - view->frame.width = configure->configure.width; - view->frame.height = configure->configure.height; - - view->backend->resize(view, - (int)view->frame.width, - (int)view->frame.height); - view->eventFunc(view, &view->impl->pendingConfigure); - } + flushPendingConfigure(view); if (mustExpose) { view->eventFunc(view, &view->impl->pendingExpose); |