aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS3
-rw-r--r--pugl/detail/mac.m9
-rw-r--r--pugl/detail/types.h1
-rw-r--r--pugl/detail/win.c24
-rw-r--r--pugl/detail/x11.c41
-rw-r--r--pugl/pugl.h8
-rw-r--r--test/pugl_cairo_test.c33
-rw-r--r--wscript1
8 files changed, 84 insertions, 36 deletions
diff --git a/AUTHORS b/AUTHORS
index c2639ab..482b17a 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -6,4 +6,5 @@ Robin Gareus <robin@gareus.org>
Erik Ã…ldstedt Sund <erikalds@gmail.com>
Hanspeter Portner <dev@open-music-kontrollers.ch>
Stefan Westerfeld <stefan@space.twc.de>
-Jordan Halase <jordan@halase.me> \ No newline at end of file
+Jordan Halase <jordan@halase.me>
+Oliver Schmidt <oliver@luced.de>
diff --git a/pugl/detail/mac.m b/pugl/detail/mac.m
index f530c2e..9378d6e 100644
--- a/pugl/detail/mac.m
+++ b/pugl/detail/mac.m
@@ -957,6 +957,15 @@ puglPostRedisplay(PuglView* view)
return PUGL_SUCCESS;
}
+PuglStatus
+puglPostRedisplayRect(PuglView* view, const PuglRect rect)
+{
+ [view->impl->drawView setNeedsDisplayInRect:
+ CGRectMake(rect.x, rect.y, rect.width, rect.height)];
+
+ return PUGL_SUCCESS;
+}
+
PuglNativeWindow
puglGetNativeWindow(PuglView* view)
{
diff --git a/pugl/detail/types.h b/pugl/detail/types.h
index d018be5..7b2934f 100644
--- a/pugl/detail/types.h
+++ b/pugl/detail/types.h
@@ -71,7 +71,6 @@ struct PuglViewImpl {
int maxAspectX;
int maxAspectY;
bool visible;
- bool redisplay;
};
/** Cross-platform world definition. */
diff --git a/pugl/detail/win.c b/pugl/detail/win.c
index ee7eb01..d7026ae 100644
--- a/pugl/detail/win.c
+++ b/pugl/detail/win.c
@@ -26,6 +26,7 @@
#include <windows.h>
#include <windowsx.h>
+#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -719,15 +720,8 @@ puglWaitForEvent(PuglView* PUGL_UNUSED(view))
}
PUGL_API PuglStatus
-puglDispatchEvents(PuglWorld* world)
+puglDispatchEvents(PuglWorld* PUGL_UNUSED(world))
{
- for (size_t i = 0; i < world->numViews; ++i) {
- if (world->views[i]->redisplay) {
- UpdateWindow(world->views[i]->impl->hwnd);
- world->views[i]->redisplay = false;
- }
- }
-
/* Windows has no facility to process only currently queued messages, which
causes the event loop to run forever in cases like mouse movement where
the queue is constantly being filled with new messages. To work around
@@ -795,7 +789,19 @@ PuglStatus
puglPostRedisplay(PuglView* view)
{
InvalidateRect(view->impl->hwnd, NULL, false);
- view->redisplay = true;
+ return PUGL_SUCCESS;
+}
+
+PuglStatus
+puglPostRedisplayRect(PuglView* view, const PuglRect rect)
+{
+ const RECT r = {(long)floor(rect.x),
+ (long)floor(rect.y),
+ (long)ceil(rect.x + rect.width),
+ (long)ceil(rect.y + rect.height)};
+
+ InvalidateRect(view->impl->hwnd, &r, false);
+
return PUGL_SUCCESS;
}
diff --git a/pugl/detail/x11.c b/pugl/detail/x11.c
index 871c16b..37280cd 100644
--- a/pugl/detail/x11.c
+++ b/pugl/detail/x11.c
@@ -38,6 +38,7 @@
#include <sys/time.h>
#include <limits.h>
+#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
@@ -615,16 +616,6 @@ mergeExposeEvents(PuglEvent* dst, const PuglEvent* src)
}
static void
-sendRedisplayEvent(PuglView* view)
-{
- XExposeEvent ev = { Expose, 0, True, view->impl->display, view->impl->win,
- 0, 0, (int)view->frame.width, (int)view->frame.height,
- 0 };
-
- XSendEvent(view->impl->display, view->impl->win, False, 0, (XEvent*)&ev);
-}
-
-static void
flushPendingConfigure(PuglView* view)
{
PuglEvent* const configure = &view->impl->pendingConfigure;
@@ -649,14 +640,6 @@ puglDispatchEvents(PuglWorld* world)
{
const PuglX11Atoms* const atoms = &world->impl->atoms;
- // Send expose events for any views with pending redisplays
- for (size_t i = 0; i < world->numViews; ++i) {
- if (world->views[i]->redisplay) {
- sendRedisplayEvent(world->views[i]);
- world->views[i]->redisplay = false;
- }
- }
-
// Flush just once at the start to fill event queue
Display* display = world->impl->display;
XFlush(display);
@@ -806,7 +789,27 @@ puglGetTime(const PuglWorld* world)
PuglStatus
puglPostRedisplay(PuglView* view)
{
- view->redisplay = true;
+ const PuglRect rect = { 0, 0, view->frame.width, view->frame.height };
+
+ return puglPostRedisplayRect(view, rect);
+}
+
+PuglStatus
+puglPostRedisplayRect(PuglView* view, PuglRect rect)
+{
+ const int x = (int)floor(rect.x);
+ const int y = (int)floor(rect.y);
+ const int w = (int)ceil(rect.x + rect.width) - x;
+ const int h = (int)ceil(rect.y + rect.height) - y;
+
+ XExposeEvent ev = {Expose, 0, True,
+ view->impl->display, view->impl->win,
+ x, y,
+ w, h,
+ 0};
+
+ XSendEvent(view->impl->display, view->impl->win, False, 0, (XEvent*)&ev);
+
return PUGL_SUCCESS;
}
diff --git a/pugl/pugl.h b/pugl/pugl.h
index 1344410..f08925f 100644
--- a/pugl/pugl.h
+++ b/pugl/pugl.h
@@ -563,12 +563,18 @@ PUGL_API bool
puglGetVisible(PuglView* view);
/**
- Request a redisplay on the next call to puglDispatchEvents().
+ Request a redisplay for the entire view.
*/
PUGL_API PuglStatus
puglPostRedisplay(PuglView* view);
/**
+ Request a redisplay of the given rectangle within the view.
+*/
+PUGL_API PuglStatus
+puglPostRedisplayRect(PuglView* view, PuglRect rect);
+
+/**
@}
@anchor frame
@name Frame
diff --git a/test/pugl_cairo_test.c b/test/pugl_cairo_test.c
index 23c2b4e..1aa291a 100644
--- a/test/pugl_cairo_test.c
+++ b/test/pugl_cairo_test.c
@@ -110,10 +110,33 @@ buttonDraw(cairo_t* cr, const Button* but, const double time)
}
static void
-onDisplay(PuglView* view)
+postButtonRedisplay(PuglView* view)
+{
+ const PuglRect frame = puglGetFrame(view);
+ const double width = frame.width;
+ const double height = frame.height;
+ const double scaleX = (width - (512 / width)) / 512.0;
+ const double scaleY = (height - (512 / height)) / 512.0;
+
+ for (Button* b = buttons; b->label; ++b) {
+ const double span = sqrt(b->w * b->w + b->h * b->h);
+ const PuglRect rect = {(b->x - span) * scaleX,
+ (b->y - span) * scaleY,
+ span * 2.0 * scaleX,
+ span * 2.0 * scaleY};
+
+ puglPostRedisplayRect(view, rect);
+ }
+}
+
+static void
+onDisplay(PuglView* view, const PuglEventExpose* event)
{
cairo_t* cr = (cairo_t*)puglGetContext(view);
+ cairo_rectangle(cr, event->x, event->y, event->width, event->height);
+ cairo_clip(cr);
+
// Draw background
const PuglRect frame = puglGetFrame(view);
const double width = frame.width;
@@ -157,11 +180,11 @@ onEvent(PuglView* view, const PuglEvent* event)
break;
case PUGL_BUTTON_PRESS:
mouseDown = true;
- puglPostRedisplay(view);
+ postButtonRedisplay(view);
break;
case PUGL_BUTTON_RELEASE:
mouseDown = false;
- puglPostRedisplay(view);
+ postButtonRedisplay(view);
break;
case PUGL_ENTER_NOTIFY:
entered = true;
@@ -172,7 +195,7 @@ onEvent(PuglView* view, const PuglEvent* event)
puglPostRedisplay(view);
break;
case PUGL_EXPOSE:
- onDisplay(view);
+ onDisplay(view, &event->expose);
break;
case PUGL_CLOSE:
onClose(view);
@@ -214,7 +237,7 @@ main(int argc, char** argv)
PuglFpsPrinter fpsPrinter = { puglGetTime(world) };
while (!quit) {
if (opts.continuous) {
- puglPostRedisplay(view);
+ postButtonRedisplay(view);
} else {
puglPollEvents(world, -1);
}
diff --git a/wscript b/wscript
index 10456d7..b9f4f25 100644
--- a/wscript
+++ b/wscript
@@ -220,6 +220,7 @@ def build(bld):
platform = 'x11'
build_platform('x11',
lib=['X11'],
+ uselib=['M'],
source=lib_source + ['pugl/detail/x11.c'])
if bld.is_defined('HAVE_GL'):