diff options
author | David Robillard <d@drobilla.net> | 2020-10-24 13:28:22 +0200 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2020-10-24 13:28:22 +0200 |
commit | 612aae5147abec2be9523c1d2858550e5d8a150d (patch) | |
tree | 2f88ed8d310af34e8c401dc14ed75f589b847a73 | |
parent | 9c2f1888f033dc577464d41cb18839b988de7987 (diff) | |
download | pugl-612aae5147abec2be9523c1d2858550e5d8a150d.tar.gz pugl-612aae5147abec2be9523c1d2858550e5d8a150d.tar.bz2 pugl-612aae5147abec2be9523c1d2858550e5d8a150d.zip |
Replace live resize with loop events
This allows the application to control how recursive loops are handled rather
than have Pugl impose behavior which can get in the way. For example, an
application may not want to continuously animate while being resized, or set up
its rendering differently in this situation. For example, with Vulkan, setting
up a different swapchain can be necessary for smooth performance while live
resizing on Windows, and Pugl has no ability to do this.
I think it was a mistake to add this timer to Pugl itself, because it was
always a bit of a leaky abstraction, and not very appropriate for a library
that is supposed to be a thin abstraction layer. Though it almost seemed like
things ran as usual while resizing on Windows and MacOS, the main event loop
being stalled can be confusing, and there was no way to detect this. This way,
applications must explicitly handle this situation and can implement the
behavior they want without Pugl getting in the way.
This also simplifies the Pugl implementation a bit, which is always nice.
-rw-r--r-- | examples/pugl_shader_demo.c | 19 | ||||
-rw-r--r-- | include/pugl/detail/implementation.c | 3 | ||||
-rw-r--r-- | include/pugl/detail/mac.m | 15 | ||||
-rw-r--r-- | include/pugl/detail/win.c | 16 | ||||
-rw-r--r-- | include/pugl/detail/win.h | 1 | ||||
-rw-r--r-- | include/pugl/pugl.h | 34 | ||||
-rw-r--r-- | include/pugl/pugl.hpp | 14 | ||||
-rw-r--r-- | include/pugl/pugl.ipp | 12 | ||||
-rw-r--r-- | test/test_utils.h | 8 |
9 files changed, 90 insertions, 32 deletions
diff --git a/examples/pugl_shader_demo.c b/examples/pugl_shader_demo.c index 1122410..4b8064d 100644 --- a/examples/pugl_shader_demo.c +++ b/examples/pugl_shader_demo.c @@ -47,12 +47,14 @@ #include <math.h> #include <stddef.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -static const int defaultWidth = 512; -static const int defaultHeight = 512; +static const int defaultWidth = 512; +static const int defaultHeight = 512; +static const uintptr_t resizeTimerId = 1u; typedef struct { @@ -166,11 +168,24 @@ onEvent(PuglView* view, const PuglEvent* event) break; case PUGL_EXPOSE: onExpose(view); break; case PUGL_CLOSE: app->quit = 1; break; + case PUGL_LOOP_ENTER: + puglStartTimer(view, + resizeTimerId, + 1.0 / (double)puglGetViewHint(view, PUGL_REFRESH_RATE)); + break; + case PUGL_LOOP_LEAVE: + puglStopTimer(view, resizeTimerId); + break; case PUGL_KEY_PRESS: if (event->key.key == 'q' || event->key.key == PUGL_KEY_ESCAPE) { app->quit = 1; } break; + case PUGL_TIMER: + if (event->timer.id == resizeTimerId) { + puglPostRedisplay(view); + } + break; default: break; } diff --git a/include/pugl/detail/implementation.c b/include/pugl/detail/implementation.c index e9a3450..f15b856 100644 --- a/include/pugl/detail/implementation.c +++ b/include/pugl/detail/implementation.c @@ -398,7 +398,8 @@ void puglDispatchSimpleEvent(PuglView* view, const PuglEventType type) { assert(type == PUGL_CREATE || type == PUGL_DESTROY || type == PUGL_MAP || - type == PUGL_UNMAP || type == PUGL_UPDATE || type == PUGL_CLOSE); + type == PUGL_UNMAP || type == PUGL_UPDATE || type == PUGL_CLOSE || + type == PUGL_LOOP_ENTER || type == PUGL_LOOP_LEAVE); const PuglEvent event = {{type, 0}}; puglDispatchEvent(view, &event); diff --git a/include/pugl/detail/mac.m b/include/pugl/detail/mac.m index efcaca0..a807761 100644 --- a/include/pugl/detail/mac.m +++ b/include/pugl/detail/mac.m @@ -190,7 +190,6 @@ updateViewRect(PuglView* view) PuglView* puglview; NSTrackingArea* trackingArea; NSMutableAttributedString* markedText; - NSTimer* timer; NSMutableDictionary* userTimers; bool reshaped; } @@ -717,15 +716,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) - (void)viewWillStartLiveResize { - timer = [NSTimer timerWithTimeInterval:(1 / 60.0) - target:self - selector:@selector(resizeTick) - userInfo:nil - repeats:YES]; - [[NSRunLoop currentRunLoop] addTimer:timer - forMode:NSRunLoopCommonModes]; - - [super viewWillStartLiveResize]; + puglDispatchSimpleEvent(puglview, PUGL_LOOP_ENTER); } - (void)viewWillDraw @@ -749,9 +740,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type) - (void)viewDidEndLiveResize { - [super viewDidEndLiveResize]; - [timer invalidate]; - timer = NULL; + puglDispatchSimpleEvent(puglview, PUGL_LOOP_LEAVE); } @end diff --git a/include/pugl/detail/win.c b/include/pugl/detail/win.c index 84cca27..237ebde 100644 --- a/include/pugl/detail/win.c +++ b/include/pugl/detail/win.c @@ -51,7 +51,6 @@ #define PUGL_LOCAL_CLOSE_MSG (WM_USER + 50) #define PUGL_LOCAL_MARK_MSG (WM_USER + 51) #define PUGL_LOCAL_CLIENT_MSG (WM_USER + 52) -#define PUGL_RESIZE_TIMER_ID 9461 #define PUGL_USER_TIMER_MIN 9470 typedef BOOL (WINAPI *PFN_SetProcessDPIAware)(void); @@ -590,17 +589,10 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_ENTERSIZEMOVE: case WM_ENTERMENULOOP: - view->impl->resizing = true; - SetTimer(view->impl->hwnd, - PUGL_RESIZE_TIMER_ID, - 1000 / (UINT)view->hints[PUGL_REFRESH_RATE], - NULL); + puglDispatchSimpleEvent(view, PUGL_LOOP_ENTER); break; case WM_TIMER: - if (wParam == PUGL_RESIZE_TIMER_ID) { - RedrawWindow(view->impl->hwnd, NULL, NULL, - RDW_INVALIDATE|RDW_ALLCHILDREN|RDW_INTERNALPAINT); - } else if (wParam >= PUGL_USER_TIMER_MIN) { + if (wParam >= PUGL_USER_TIMER_MIN) { PuglEvent ev = {{PUGL_TIMER, 0}}; ev.timer.id = wParam - PUGL_USER_TIMER_MIN; puglDispatchEvent(view, &ev); @@ -608,9 +600,7 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_EXITSIZEMOVE: case WM_EXITMENULOOP: - KillTimer(view->impl->hwnd, PUGL_RESIZE_TIMER_ID); - view->impl->resizing = false; - puglPostRedisplay(view); + puglDispatchSimpleEvent(view, PUGL_LOOP_LEAVE); break; case WM_GETMINMAXINFO: mmi = (MINMAXINFO*)lParam; diff --git a/include/pugl/detail/win.h b/include/pugl/detail/win.h index 0ead1fa..4c0a3c0 100644 --- a/include/pugl/detail/win.h +++ b/include/pugl/detail/win.h @@ -42,7 +42,6 @@ struct PuglInternalsImpl { HDC hdc; PuglSurface* surface; bool flashing; - bool resizing; bool mouseTracked; }; diff --git a/include/pugl/pugl.h b/include/pugl/pugl.h index 1ec5491..19f9fa4 100644 --- a/include/pugl/pugl.h +++ b/include/pugl/pugl.h @@ -200,6 +200,8 @@ typedef enum { PUGL_SCROLL, ///< Scrolled, a #PuglEventScroll PUGL_CLIENT, ///< Custom client message, a #PuglEventClient PUGL_TIMER, ///< Timer triggered, a #PuglEventTimer + PUGL_LOOP_ENTER, ///< Recursive loop entered, a #PuglEventLoopEnter + PUGL_LOOP_LEAVE, ///< Recursive loop left, a #PuglEventLoopLeave #ifndef PUGL_DISABLE_DEPRECATED PUGL_ENTER_NOTIFY PUGL_DEPRECATED_BY("PUGL_POINTER_IN") = PUGL_POINTER_IN, @@ -515,6 +517,38 @@ typedef struct { } PuglEventTimer; /** + Recursive loop enter event. + + This event is sent when the window system enters a recursive loop. The main + loop will be stalled and no expose events will be received while in the + recursive loop. To give the application full control, Pugl does not do any + special handling of this situation, but this event can be used to install a + timer to perform continuous actions (such as drawing) on platforms that do + this. + + - MacOS: A recursive loop is entered while the window is being live resized. + + - Windows: A recursive loop is entered while the window is being live + resized or the menu is shown. + + - X11: A recursive loop is never entered and the event loop runs as usual + while the view is being resized. + + This event type has no extra fields. +*/ +typedef PuglEventAny PuglEventLoopEnter; + +/** + Recursive loop leave event. + + This event is sent after a loop enter event when the recursive loop is + finished and normal iteration will continue. + + This event type has no extra fields. +*/ +typedef PuglEventAny PuglEventLoopLeave; + +/** View event. This is a union of all event types. The type must be checked to determine diff --git a/include/pugl/pugl.hpp b/include/pugl/pugl.hpp index 2097534..7650b1f 100644 --- a/include/pugl/pugl.hpp +++ b/include/pugl/pugl.hpp @@ -176,6 +176,12 @@ using ClientEvent = Event<PUGL_CLIENT, PuglEventClient>; /// @copydoc PuglEventTimer using TimerEvent = Event<PUGL_TIMER, PuglEventTimer>; +/// @copydoc PuglEventLoopEnter +using LoopEnterEvent = Event<PUGL_LOOP_ENTER, PuglEventLoopEnter>; + +/// @copydoc PuglEventLoopLeave +using LoopLeaveEvent = Event<PUGL_LOOP_LEAVE, PuglEventLoopLeave>; + /** @} @name Status @@ -610,6 +616,8 @@ public: virtual Status onScroll(const ScrollEvent&) PUGL_CONST_FUNC; virtual Status onClient(const ClientEvent&) PUGL_CONST_FUNC; virtual Status onTimer(const TimerEvent&) PUGL_CONST_FUNC; + virtual Status onLoopEnter(const LoopEnterEvent&) PUGL_CONST_FUNC; + virtual Status onLoopLeave(const LoopLeaveEvent&) PUGL_CONST_FUNC; /** @} @@ -709,6 +717,12 @@ private: case PUGL_TIMER: return static_cast<PuglStatus>( onTimer(typedEventRef<TimerEvent>(event->timer))); + case PUGL_LOOP_ENTER: + return static_cast<PuglStatus>( + onLoopEnter(typedEventRef<LoopEnterEvent>(event->any))); + case PUGL_LOOP_LEAVE: + return static_cast<PuglStatus>( + onLoopLeave(typedEventRef<LoopLeaveEvent>(event->any))); } return PUGL_FAILURE; diff --git a/include/pugl/pugl.ipp b/include/pugl/pugl.ipp index 0ed8c4d..aa6e6f1 100644 --- a/include/pugl/pugl.ipp +++ b/include/pugl/pugl.ipp @@ -151,4 +151,16 @@ View::onTimer(const TimerEvent&) return pugl::Status::success; } +Status +View::onLoopEnter(const LoopEnterEvent&) +{ + return pugl::Status::success; +} + +Status +View::onLoopLeave(const LoopLeaveEvent&) +{ + return pugl::Status::success; +} + } // namespace pugl diff --git a/test/test_utils.h b/test/test_utils.h index d86018c..7a91535 100644 --- a/test/test_utils.h +++ b/test/test_utils.h @@ -173,8 +173,10 @@ printEvent(const PuglEvent* event, const char* prefix, const bool verbose) prefix, event->client.data1, event->client.data2); - case PUGL_TIMER: - return PRINT("%sTimer %" PRIuPTR "\n", prefix, event->timer.id); + case PUGL_LOOP_ENTER: + return PRINT("%sLoop enter\n", prefix); + case PUGL_LOOP_LEAVE: + return PRINT("%sLoop leave\n", prefix); default: break; } @@ -212,6 +214,8 @@ printEvent(const PuglEvent* event, const char* prefix, const bool verbose) prefix, event->motion.x, event->motion.y); + case PUGL_TIMER: + return PRINT("%sTimer %" PRIuPTR "\n", prefix, event->timer.id); default: return PRINT("%sUnknown event type %d\n", prefix, (int)event->type); } |