=> 6a565ea71745aaf4c91a7698bbf56f7d906fcaaa
[1mdiff --git a/CMakeLists.txt b/CMakeLists.txt[m [1mindex 82d55590..0edfbed2 100644[m [1m--- a/CMakeLists.txt[m [1m+++ b/CMakeLists.txt[m [36m@@ -30,6 +30,7 @@[m [moption (ENABLE_X11_SWRENDER "Use software rendering under X11" OFF)[m option (ENABLE_KERNING "Enable kerning in font renderer (slower)" ON)[m option (ENABLE_RESOURCE_EMBED "Embed resources inside the executable" OFF)[m option (ENABLE_WINDOWPOS_FIX "Set position after showing window (workaround for SDL bug)" OFF)[m [32m+[m[32moption (ENABLE_IDLE_SLEEP "While idle, sleep in the main thread instead of waiting for events" ON)[m [m include (BuildType.cmake)[m include (res/Embed.cmake)[m [36m@@ -219,6 +220,9 @@[m [mif (ENABLE_MPG123 AND MPG123_FOUND)[m target_compile_definitions (app PUBLIC LAGRANGE_ENABLE_MPG123=1)[m target_link_libraries (app PUBLIC PkgConfig::MPG123)[m endif ()[m [32m+[m[32mif (ENABLE_IDLE_SLEEP)[m [32m+[m[32m target_compile_definitions (app PUBLIC LAGRANGE_IDLE_SLEEP=1)[m [32m+[m[32mendif ()[m target_link_libraries (app PUBLIC the_Foundation::the_Foundation)[m target_link_libraries (app PUBLIC ${SDL2_LDFLAGS})[m if (APPLE)[m [1mdiff --git a/res/about/version.gmi b/res/about/version.gmi[m [1mindex af758486..5944932f 100644[m [1m--- a/res/about/version.gmi[m [1m+++ b/res/about/version.gmi[m [36m@@ -10,6 +10,7 @@[m * 'text/*' content falls back to plain text.[m * Reduced visual artifacts in Unicode box-drawing characters (overlapping/gaps).[m * Fixed truncated tab titles when opening tabs in background.[m [32m+[m[32m* macOS: Fixed excessive CPU usage while idling.[m [m ## 0.12[m * Added MIME hooks: pipe Gemini responses through external programs for arbitrary processing. (See "about:help" for usage.)[m [1mdiff --git a/src/app.c b/src/app.c[m [1mindex 1e0a847d..ba7d41d2 100644[m [1m--- a/src/app.c[m [1m+++ b/src/app.c[m [36m@@ -89,6 +89,8 @@[m [mstatic const char *prefsFileName_App_ = "prefs.cfg";[m static const char *stateFileName_App_ = "state.binary";[m static const char *downloadDir_App_ = "~/Downloads";[m [m [32m+[m[32mstatic const int idleThreshold_App_ = 1000; /* ms */[m [32m+[m struct Impl_App {[m iCommandLine args;[m iString * execPath;[m [36m@@ -100,7 +102,12 @@[m [mstruct Impl_App {[m iSortedArray tickers;[m uint32_t lastTickerTime;[m uint32_t elapsedSinceLastTicker;[m [31m- iBool running;[m [32m+[m[32m iBool isRunning;[m [32m+[m[32m#if defined (LAGRANGE_IDLE_SLEEP)[m [32m+[m[32m iBool isIdling;[m [32m+[m[32m uint32_t lastEventTime;[m [32m+[m[32m int sleepTimer;[m [32m+[m[32m#endif[m iAtomicInt pendingRefresh;[m int tabEnum;[m iStringList *launchCommands;[m [36m@@ -320,6 +327,16 @@[m [mstatic void saveState_App_(const iApp *d) {[m iRelease(f);[m }[m [m [32m+[m[32m#if defined (LAGRANGE_IDLE_SLEEP)[m [32m+[m[32mstatic uint32_t checkAsleep_App_(uint32_t interval, void *param) {[m [32m+[m[32m iApp *d = param;[m [32m+[m[32m SDL_Event ev = { .type = SDL_USEREVENT };[m [32m+[m[32m ev.user.code = asleep_UserEventCode;[m [32m+[m[32m SDL_PushEvent(&ev);[m [32m+[m[32m return interval;[m [32m+[m[32m}[m [32m+[m[32m#endif[m [32m+[m static void init_App_(iApp *d, int argc, char **argv) {[m const iBool isFirstRun = !fileExistsCStr_FileInfo(cleanedPath_CStr(dataDir_App_));[m d->isFinishedLaunching = iFalse;[m [36m@@ -349,7 +366,7 @@[m [mstatic void init_App_(iApp *d, int argc, char **argv) {[m #endif[m init_Prefs(&d->prefs);[m setCStr_String(&d->prefs.downloadDir, downloadDir_App_);[m [31m- d->running = iFalse;[m [32m+[m[32m d->isRunning = iFalse;[m d->window = NULL;[m set_Atomic(&d->pendingRefresh, iFalse);[m d->mimehooks = new_MimeHooks();[m [36m@@ -358,6 +375,11 @@[m [mstatic void init_App_(iApp *d, int argc, char **argv) {[m d->bookmarks = new_Bookmarks();[m d->tabEnum = 0; /* generates unique IDs for tab pages */[m setThemePalette_Color(d->prefs.theme);[m [32m+[m[32m#if defined (LAGRANGE_IDLE_SLEEP)[m [32m+[m[32m d->isIdling = iFalse;[m [32m+[m[32m d->lastEventTime = 0;[m [32m+[m[32m d->sleepTimer = SDL_AddTimer(1000, checkAsleep_App_, d);[m [32m+[m[32m#endif[m #if defined (iPlatformApple)[m setupApplication_MacOS();[m #endif[m [36m@@ -484,19 +506,25 @@[m [mconst iString *debugInfo_App(void) {[m }[m [m iLocalDef iBool isWaitingAllowed_App_(iApp *d) {[m [32m+[m[32m#if defined (LAGRANGE_IDLE_SLEEP)[m [32m+[m[32m if (d->isIdling) {[m [32m+[m[32m return iFalse;[m [32m+[m[32m }[m [32m+[m[32m#endif[m return !value_Atomic(&d->pendingRefresh) && isEmpty_SortedArray(&d->tickers);[m }[m [m void processEvents_App(enum iAppEventMode eventMode) {[m iApp *d = &app_;[m SDL_Event ev;[m [32m+[m[32m iBool gotEvents = iFalse;[m while ((isWaitingAllowed_App_(d) && eventMode == waitForNewEvents_AppEventMode &&[m SDL_WaitEvent(&ev)) ||[m ((!isWaitingAllowed_App_(d) || eventMode == postedEventsOnly_AppEventMode) &&[m SDL_PollEvent(&ev))) {[m switch (ev.type) {[m case SDL_QUIT:[m [31m- d->running = iFalse;[m [32m+[m[32m d->isRunning = iFalse;[m goto backToMainLoop;[m case SDL_DROPFILE: {[m iBool newTab = iFalse;[m [36m@@ -516,6 +544,25 @@[m [mvoid processEvents_App(enum iAppEventMode eventMode) {[m break;[m }[m default: {[m [32m+[m[32m#if defined (LAGRANGE_IDLE_SLEEP)[m [32m+[m[32m if (ev.type == SDL_USEREVENT && ev.user.code == asleep_UserEventCode) {[m [32m+[m[32m if (SDL_GetTicks() - d->lastEventTime > idleThreshold_App_) {[m [32m+[m[32m if (!d->isIdling) {[m [32m+[m[32m printf("[App] idling...\n");[m [32m+[m[32m fflush(stdout);[m [32m+[m[32m }[m [32m+[m[32m d->isIdling = iTrue;[m [32m+[m[32m }[m [32m+[m[32m continue;[m [32m+[m[32m }[m [32m+[m[32m d->lastEventTime = SDL_GetTicks();[m [32m+[m[32m if (d->isIdling) {[m [32m+[m[32m printf("[App] ...woke up\n");[m [32m+[m[32m fflush(stdout);[m [32m+[m[32m }[m [32m+[m[32m d->isIdling = iFalse;[m [32m+[m[32m#endif[m [32m+[m[32m gotEvents = iTrue;[m iBool wasUsed = processEvent_Window(d->window, &ev);[m if (!wasUsed) {[m /* There may be a key bindings for this. */[m [36m@@ -539,6 +586,14 @@[m [mvoid processEvents_App(enum iAppEventMode eventMode) {[m }[m }[m }[m [32m+[m[32m#if defined (LAGRANGE_IDLE_SLEEP)[m [32m+[m[32m if (d->isIdling && !gotEvents) {[m [32m+[m[32m /* This is where we spend most of our time when idle. 60 Hz still quite a lot but we[m [32m+[m[32m can't wait too long after the user tries to interact again with the app. In any[m [32m+[m[32m case, on macOS SDL_WaitEvent() seems to use 10x more CPU time than sleeping. */[m [32m+[m[32m SDL_Delay(1000 / 60);[m [32m+[m[32m }[m [32m+[m[32m#endif[m backToMainLoop:;[m }[m [m [36m@@ -586,10 +641,10 @@[m [mstatic int resizeWatcher_(void *user, SDL_Event *event) {[m [m static int run_App_(iApp *d) {[m arrange_Widget(findWidget_App("root"));[m [31m- d->running = iTrue;[m [32m+[m[32m d->isRunning = iTrue;[m SDL_EventState(SDL_DROPFILE, SDL_ENABLE); /* open files via drag'n'drop */[m SDL_AddEventWatch(resizeWatcher_, d);[m [31m- while (d->running) {[m [32m+[m[32m while (d->isRunning) {[m processEvents_App(waitForNewEvents_AppEventMode);[m runTickers_App_(d);[m refresh_App();[m [36m@@ -600,6 +655,9 @@[m [mstatic int run_App_(iApp *d) {[m [m void refresh_App(void) {[m iApp *d = &app_;[m [32m+[m[32m#if defined (LAGRANGE_IDLE_SLEEP)[m [32m+[m[32m if (d->isIdling) return;[m [32m+[m[32m#endif[m destroyPending_Widget();[m draw_Window(d->window);[m set_Atomic(&d->pendingRefresh, iFalse);[m [36m@@ -657,6 +715,9 @@[m [mint run_App(int argc, char **argv) {[m [m void postRefresh_App(void) {[m iApp *d = &app_;[m [32m+[m[32m#if defined (LAGRANGE_IDLE_SLEEP)[m [32m+[m[32m d->isIdling = iFalse;[m [32m+[m[32m#endif[m const iBool wasPending = exchange_Atomic(&d->pendingRefresh, iTrue);[m if (!wasPending) {[m SDL_Event ev;[m [36m@@ -1085,12 +1146,12 @@[m [miBool handleCommand_App(const char *cmd) {[m }[m else if (equal_Command(cmd, "prefs.sideicon.changed")) {[m d->prefs.sideIcon = arg_Command(cmd) != 0;[m [31m- refresh_App();[m [32m+[m[32m postRefresh_App();[m return iTrue;[m }[m else if (equal_Command(cmd, "prefs.hoveroutline.changed")) {[m d->prefs.hoverOutline = arg_Command(cmd) != 0;[m [31m- refresh_App();[m [32m+[m[32m postRefresh_App();[m return iTrue;[m }[m else if (equal_Command(cmd, "saturation.set")) {[m [36m@@ -1373,13 +1434,13 @@[m [miBool handleCommand_App(const char *cmd) {[m }[m else if (equal_Command(cmd, "feeds.update.started")) {[m setFlags_Widget(findWidget_App("feeds.progress"), hidden_WidgetFlag, iFalse);[m [31m- refresh_App();[m [32m+[m[32m postRefresh_App();[m return iFalse;[m }[m else if (equal_Command(cmd, "feeds.update.finished")) {[m setFlags_Widget(findWidget_App("feeds.progress"), hidden_WidgetFlag, iTrue);[m refreshFinished_Feeds();[m [31m- refresh_App();[m [32m+[m[32m postRefresh_App();[m return iFalse;[m }[m else if (equal_Command(cmd, "visited.changed")) {[m [1mdiff --git a/src/app.h b/src/app.h[m [1mindex bc086dfe..743484a5 100644[m [1m--- a/src/app.h[m [1m+++ b/src/app.h[m [36m@@ -46,6 +46,7 @@[m [menum iAppEventMode {[m enum iUserEventCode {[m command_UserEventCode = 1,[m refresh_UserEventCode = 2,[m [32m+[m[32m asleep_UserEventCode = 3,[m };[m [m const iString *execPath_App (void);[m
text/gemini; charset=utf-8
This content has been proxied by September (ba2dc).