diff options
-rw-r--r-- | src/app.c | 32 | ||||
-rw-r--r-- | src/periodic.c | 44 | ||||
-rw-r--r-- | src/periodic.h | 16 | ||||
-rw-r--r-- | src/ui/scrollwidget.c | 2 |
4 files changed, 51 insertions, 43 deletions
@@ -837,6 +837,9 @@ void trimCache_App(void) { | |||
837 | } | 837 | } |
838 | 838 | ||
839 | iLocalDef iBool isWaitingAllowed_App_(iApp *d) { | 839 | iLocalDef 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 | ||
859 | static 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 | |||
856 | void processEvents_App(enum iAppEventMode eventMode) { | 873 | void 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 | ||
1065 | void refresh_App(void) { | 1080 | void 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) { | 55 | static const uint32_t postingInterval_Periodic_ = 500; |
56 | static iThreadResult poster_Periodic_(iThread *thread) { | 56 | |
57 | iPeriodic *d = userData_Thread(thread); | 57 | iBool 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 | ||
77 | void init_Periodic(iPeriodic *d) { | 73 | void 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 | ||
88 | void deinit_Periodic(iPeriodic *d) { | 79 | void 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. */ | |||
26 | iDeclareType(Periodic) | 26 | iDeclareType(Periodic) |
27 | iDeclareType(Thread) | 27 | iDeclareType(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. */ |
30 | struct Impl_Periodic { | 30 | struct 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 | ||
38 | void init_Periodic (iPeriodic *); | 36 | void init_Periodic (iPeriodic *); |
39 | void deinit_Periodic (iPeriodic *); | 37 | void deinit_Periodic (iPeriodic *); |
40 | 38 | ||
41 | void add_Periodic (iPeriodic *, iAny *context, const char *command); | 39 | iLocalDef iBool isEmpty_Periodic(const iPeriodic *d) { |
42 | void remove_Periodic (iPeriodic *, iAny *context); | 40 | return isEmpty_SortedArray(&d->commands); |
41 | } | ||
42 | |||
43 | void add_Periodic (iPeriodic *, iAny *context, const char *command); | ||
44 | void remove_Periodic (iPeriodic *, iAny *context); | ||
45 | |||
46 | iBool 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 | } |