aboutsummaryrefslogtreecommitdiff
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
parentd53ce364a7c7c0d9b0d1fa87077df2dff69688e9 (diff)
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.
-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);