aboutsummaryrefslogtreecommitdiffstats
path: root/pugl/detail
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2019-11-03 19:02:38 +0100
committerDavid Robillard <d@drobilla.net>2019-11-03 21:03:18 +0100
commitd9239872c71d117f78ce6c109cd9ab42e2d80c6b (patch)
tree7a25bbe867d750155711577deaa604a2ad722632 /pugl/detail
parentd53ce364a7c7c0d9b0d1fa87077df2dff69688e9 (diff)
downloadpugl-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.c58
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);