summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/app.c32
-rw-r--r--src/periodic.c44
-rw-r--r--src/periodic.h16
-rw-r--r--src/ui/scrollwidget.c2
4 files changed, 51 insertions, 43 deletions
diff --git a/src/app.c b/src/app.c
index 31bd33ed..0611b6dd 100644
--- a/src/app.c
+++ b/src/app.c
@@ -837,6 +837,9 @@ void trimCache_App(void) {
837} 837}
838 838
839iLocalDef iBool isWaitingAllowed_App_(iApp *d) { 839iLocalDef iBool isWaitingAllowed_App_(iApp *d) {
840 if (!isEmpty_Periodic(&d->periodic)) {
841 return iFalse;
842 }
840 if (d->warmupFrames > 0) { 843 if (d->warmupFrames > 0) {
841 return iFalse; 844 return iFalse;
842 } 845 }
@@ -853,14 +856,26 @@ iLocalDef iBool isWaitingAllowed_App_(iApp *d) {
853 return !value_Atomic(&d->pendingRefresh) && isEmpty_SortedArray(&d->tickers); 856 return !value_Atomic(&d->pendingRefresh) && isEmpty_SortedArray(&d->tickers);
854} 857}
855 858
859static iBool nextEvent_App_(iApp *d, enum iAppEventMode eventMode, SDL_Event *event) {
860 if (eventMode == waitForNewEvents_AppEventMode && isWaitingAllowed_App_(d)) {
861 /* If there are periodic commands pending, wait only for a short while. */
862 if (!isEmpty_Periodic(&d->periodic)) {
863 return SDL_WaitEventTimeout(event, 500);
864 }
865 /* We may be allowed to block here until an event comes in. */
866 if (isWaitingAllowed_App_(d)) {
867 return SDL_WaitEvent(event);
868 }
869 }
870 return SDL_PollEvent(event);
871}
872
856void processEvents_App(enum iAppEventMode eventMode) { 873void processEvents_App(enum iAppEventMode eventMode) {
857 iApp *d = &app_; 874 iApp *d = &app_;
858 SDL_Event ev; 875 SDL_Event ev;
859 iBool gotEvents = iFalse; 876 iBool gotEvents = iFalse;
860 while ((isWaitingAllowed_App_(d) && eventMode == waitForNewEvents_AppEventMode && 877 postCommands_Periodic(&d->periodic);
861 SDL_WaitEvent(&ev)) || 878 while (nextEvent_App_(d, eventMode, &ev)) {
862 ((!isWaitingAllowed_App_(d) || eventMode == postedEventsOnly_AppEventMode) &&
863 SDL_PollEvent(&ev))) {
864#if defined (iPlatformAppleMobile) 879#if defined (iPlatformAppleMobile)
865 if (processEvent_iOS(&ev)) { 880 if (processEvent_iOS(&ev)) {
866 continue; 881 continue;
@@ -1064,13 +1079,18 @@ static int run_App_(iApp *d) {
1064 1079
1065void refresh_App(void) { 1080void refresh_App(void) {
1066 iApp *d = &app_; 1081 iApp *d = &app_;
1082 destroyPending_Widget();
1067#if defined (LAGRANGE_IDLE_SLEEP) 1083#if defined (LAGRANGE_IDLE_SLEEP)
1068 if (d->warmupFrames == 0 && d->isIdling) { 1084 if (d->warmupFrames == 0 && d->isIdling) {
1069 return; 1085 return;
1070 } 1086 }
1071#endif 1087#endif
1072 set_Atomic(&d->pendingRefresh, iFalse); 1088 if (!exchange_Atomic(&d->pendingRefresh, iFalse)) {
1073 destroyPending_Widget(); 1089 /* Refreshing wasn't pending. */
1090 if (isFinished_Anim(&d->window->rootOffset)) {
1091 return;
1092 }
1093 }
1074// iTime draw; 1094// iTime draw;
1075// initCurrent_Time(&draw); 1095// initCurrent_Time(&draw);
1076 draw_Window(d->window); 1096 draw_Window(d->window);
diff --git a/src/periodic.c b/src/periodic.c
index c039097d..29c26de9 100644
--- a/src/periodic.c
+++ b/src/periodic.c
@@ -52,50 +52,35 @@ iDefineTypeConstructionArgs(PeriodicCommand, (iAny *ctx, const char *cmd), ctx,
52 52
53/*----------------------------------------------------------------------------------------------*/ 53/*----------------------------------------------------------------------------------------------*/
54 54
55//static uint32_t postCommands_Periodic_(uint32_t interval, void *param) { 55static const uint32_t postingInterval_Periodic_ = 500;
56static iThreadResult poster_Periodic_(iThread *thread) { 56
57 iPeriodic *d = userData_Thread(thread); 57iBool postCommands_Periodic(iPeriodic *d) {
58 const uint32_t now = SDL_GetTicks();
59 if (now - d->lastPostTime < postingInterval_Periodic_) {
60 return iFalse;
61 }
62 d->lastPostTime = now;
63 iBool wasPosted = iFalse;
58 lock_Mutex(d->mutex); 64 lock_Mutex(d->mutex);
59 while (!value_Atomic(&d->isStopping)) { 65 iConstForEach(Array, i, &d->commands.values) {
60 if (isEmpty_SortedArray(&d->commands)) { 66 postCommandString_App(&((const iPeriodicCommand *) i.value)->command);
61 /* Sleep until we have something to post. */ 67 wasPosted = iTrue;
62 wait_Condition(&d->haveCommands, d->mutex);
63 continue;
64 }
65 iConstForEach(Array, i, &d->commands.values) {
66 postCommandString_App(&((const iPeriodicCommand *) i.value)->command);
67 }
68 /* Sleep for a while. */
69 iTime until;
70 initTimeout_Time(&until, 0.5f);
71 waitTimeout_Condition(&d->haveCommands, d->mutex, &until);
72 } 68 }
73 unlock_Mutex(d->mutex); 69 unlock_Mutex(d->mutex);
74 return 0; 70 return wasPosted;
75} 71}
76 72
77void init_Periodic(iPeriodic *d) { 73void init_Periodic(iPeriodic *d) {
78 d->mutex = new_Mutex(); 74 d->mutex = new_Mutex();
79 init_SortedArray(&d->commands, sizeof(iPeriodicCommand), cmp_PeriodicCommand_); 75 init_SortedArray(&d->commands, sizeof(iPeriodicCommand), cmp_PeriodicCommand_);
80// d->timer = SDL_AddTimer(500, postCommands_Periodic_, d); 76 d->lastPostTime = 0;
81 set_Atomic(&d->isStopping, iFalse);
82 init_Condition(&d->haveCommands);
83 d->thread = new_Thread(poster_Periodic_);
84 setUserData_Thread(d->thread, d);
85 start_Thread(d->thread);
86} 77}
87 78
88void deinit_Periodic(iPeriodic *d) { 79void deinit_Periodic(iPeriodic *d) {
89// SDL_RemoveTimer(d->timer);
90 set_Atomic(&d->isStopping, iTrue);
91 signal_Condition(&d->haveCommands);
92 join_Thread(d->thread);
93 iRelease(d->thread);
94 iForEach(Array, i, &d->commands.values) { 80 iForEach(Array, i, &d->commands.values) {
95 deinit_PeriodicCommand(i.value); 81 deinit_PeriodicCommand(i.value);
96 } 82 }
97 deinit_SortedArray(&d->commands); 83 deinit_SortedArray(&d->commands);
98 deinit_Condition(&d->haveCommands);
99 delete_Mutex(d->mutex); 84 delete_Mutex(d->mutex);
100} 85}
101 86
@@ -112,7 +97,6 @@ void add_Periodic(iPeriodic *d, iAny *context, const char *command) {
112 init_PeriodicCommand(&pc, context, command); 97 init_PeriodicCommand(&pc, context, command);
113 insert_SortedArray(&d->commands, &pc); 98 insert_SortedArray(&d->commands, &pc);
114 } 99 }
115 signal_Condition(&d->haveCommands);
116 unlock_Mutex(d->mutex); 100 unlock_Mutex(d->mutex);
117} 101}
118 102
diff --git a/src/periodic.h b/src/periodic.h
index c643a2fe..db90b848 100644
--- a/src/periodic.h
+++ b/src/periodic.h
@@ -26,17 +26,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
26iDeclareType(Periodic) 26iDeclareType(Periodic)
27iDeclareType(Thread) 27iDeclareType(Thread)
28 28
29/* Animation utility. Not per frame but several times per second. */ 29/* Animation utility. Not per frame but several times per second. Thread safe. */
30struct Impl_Periodic { 30struct Impl_Periodic {
31 iMutex * mutex; 31 iMutex * mutex;
32 iSortedArray commands; 32 iSortedArray commands;
33 iCondition haveCommands; 33 uint32_t lastPostTime;
34 iThread * thread;
35 iAtomicInt isStopping;
36}; 34};
37 35
38void init_Periodic (iPeriodic *); 36void init_Periodic (iPeriodic *);
39void deinit_Periodic (iPeriodic *); 37void deinit_Periodic (iPeriodic *);
40 38
41void add_Periodic (iPeriodic *, iAny *context, const char *command); 39iLocalDef iBool isEmpty_Periodic(const iPeriodic *d) {
42void remove_Periodic (iPeriodic *, iAny *context); 40 return isEmpty_SortedArray(&d->commands);
41}
42
43void add_Periodic (iPeriodic *, iAny *context, const char *command);
44void remove_Periodic (iPeriodic *, iAny *context);
45
46iBool postCommands_Periodic (iPeriodic *);
diff --git a/src/ui/scrollwidget.c b/src/ui/scrollwidget.c
index b5b204a1..55ede426 100644
--- a/src/ui/scrollwidget.c
+++ b/src/ui/scrollwidget.c
@@ -112,7 +112,7 @@ static void unfade_ScrollWidget_(iScrollWidget *d, float opacity) {
112 d->willCheckFade = iTrue; 112 d->willCheckFade = iTrue;
113 /* TODO: This causes an inexplicable refresh issue on macOS: the drawing of one frame 113 /* TODO: This causes an inexplicable refresh issue on macOS: the drawing of one frame
114 takes 100ms for some reason (not the current frame but some time after). */ 114 takes 100ms for some reason (not the current frame but some time after). */
115// add_Periodic(periodic_App(), d, "scrollbar.fade"); 115 add_Periodic(periodic_App(), d, "scrollbar.fade");
116 } 116 }
117 refresh_Widget(d); 117 refresh_Widget(d);
118} 118}