summaryrefslogtreecommitdiff
path: root/src/app.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-06-25 16:26:53 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-06-25 16:26:53 +0300
commit5dbc85eaaa1bd0a0fc11dd76a75ece2efe763df5 (patch)
tree9721fb7aced603adb10b9bb3f3beb3f8d5fba973 /src/app.c
parent95c527db1484f7758a180c6de051d0182c3b2e81 (diff)
parentf99a9111170f2ff28383fd3172fdaf4b9a1ba069 (diff)
Merge branch 'work/v1.6' into work/serious-unicode
# Conflicts: # res/fonts/SmolEmoji-Regular.ttf
Diffstat (limited to 'src/app.c')
-rw-r--r--src/app.c156
1 files changed, 147 insertions, 9 deletions
diff --git a/src/app.c b/src/app.c
index 663fa2e8..b25a213e 100644
--- a/src/app.c
+++ b/src/app.c
@@ -59,6 +59,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
59#include <stdarg.h> 59#include <stdarg.h>
60#include <errno.h> 60#include <errno.h>
61 61
62//#define LAGRANGE_ENABLE_MOUSE_TOUCH_EMULATION 1
63
62#if defined (iPlatformAppleDesktop) 64#if defined (iPlatformAppleDesktop)
63# include "macos.h" 65# include "macos.h"
64#endif 66#endif
@@ -210,6 +212,7 @@ static iString *serializePrefs_App_(const iApp *d) {
210 appendFormat_String(str, "smoothscroll arg:%d\n", d->prefs.smoothScrolling); 212 appendFormat_String(str, "smoothscroll arg:%d\n", d->prefs.smoothScrolling);
211 appendFormat_String(str, "imageloadscroll arg:%d\n", d->prefs.loadImageInsteadOfScrolling); 213 appendFormat_String(str, "imageloadscroll arg:%d\n", d->prefs.loadImageInsteadOfScrolling);
212 appendFormat_String(str, "cachesize.set arg:%d\n", d->prefs.maxCacheSize); 214 appendFormat_String(str, "cachesize.set arg:%d\n", d->prefs.maxCacheSize);
215 appendFormat_String(str, "memorysize.set arg:%d\n", d->prefs.maxMemorySize);
213 appendFormat_String(str, "decodeurls arg:%d\n", d->prefs.decodeUserVisibleURLs); 216 appendFormat_String(str, "decodeurls arg:%d\n", d->prefs.decodeUserVisibleURLs);
214 appendFormat_String(str, "linewidth.set arg:%d\n", d->prefs.lineWidth); 217 appendFormat_String(str, "linewidth.set arg:%d\n", d->prefs.lineWidth);
215 /* TODO: Set up an array of booleans in Prefs and do these in a loop. */ 218 /* TODO: Set up an array of booleans in Prefs and do these in a loop. */
@@ -760,6 +763,7 @@ static void init_App_(iApp *d, int argc, char **argv) {
760 setupApplication_iOS(); 763 setupApplication_iOS();
761#endif 764#endif
762 init_Keys(); 765 init_Keys();
766 loadPalette_Color(dataDir_App_());
763 setThemePalette_Color(d->prefs.theme); /* default UI colors */ 767 setThemePalette_Color(d->prefs.theme); /* default UI colors */
764 loadPrefs_App_(d); 768 loadPrefs_App_(d);
765 load_Keys(dataDir_App_()); 769 load_Keys(dataDir_App_());
@@ -918,13 +922,25 @@ const iString *debugInfo_App(void) {
918 extern char **environ; /* The environment variables. */ 922 extern char **environ; /* The environment variables. */
919 iApp *d = &app_; 923 iApp *d = &app_;
920 iString *msg = collectNew_String(); 924 iString *msg = collectNew_String();
925 iObjectList *docs = iClob(listDocuments_App(NULL));
921 format_String(msg, "# Debug information\n"); 926 format_String(msg, "# Debug information\n");
927 appendFormat_String(msg, "## Memory usage\n"); {
928 iMemInfo total = { 0, 0 };
929 iForEach(ObjectList, i, docs) {
930 iDocumentWidget *doc = i.object;
931 iMemInfo usage = memoryUsage_History(history_DocumentWidget(doc));
932 total.cacheSize += usage.cacheSize;
933 total.memorySize += usage.memorySize;
934 }
935 appendFormat_String(msg, "Total cache: %.3f MB\n", total.cacheSize / 1.0e6f);
936 appendFormat_String(msg, "Total memory: %.3f MB\n", total.memorySize / 1.0e6f);
937 }
922 appendFormat_String(msg, "## Documents\n"); 938 appendFormat_String(msg, "## Documents\n");
923 iForEach(ObjectList, k, iClob(listDocuments_App(NULL))) { 939 iForEach(ObjectList, k, docs) {
924 iDocumentWidget *doc = k.object; 940 iDocumentWidget *doc = k.object;
925 appendFormat_String(msg, "### Tab %d.%zu: %s\n", 941 appendFormat_String(msg, "### Tab %d.%zu: %s\n",
926 constAs_Widget(doc)->root == get_Window()->roots[0] ? 0 : 1, 942 constAs_Widget(doc)->root == get_Window()->roots[0] ? 1 : 2,
927 childIndex_Widget(constAs_Widget(doc)->parent, k.object), 943 childIndex_Widget(constAs_Widget(doc)->parent, k.object) + 1,
928 cstr_String(bookmarkTitle_DocumentWidget(doc))); 944 cstr_String(bookmarkTitle_DocumentWidget(doc)));
929 append_String(msg, collect_String(debugInfo_History(history_DocumentWidget(doc)))); 945 append_String(msg, collect_String(debugInfo_History(history_DocumentWidget(doc))));
930 } 946 }
@@ -979,6 +995,33 @@ void trimCache_App(void) {
979 iRelease(docs); 995 iRelease(docs);
980} 996}
981 997
998void trimMemory_App(void) {
999 iApp *d = &app_;
1000 size_t memorySize = 0;
1001 const size_t limit = d->prefs.maxMemorySize * 1000000;
1002 iObjectList *docs = listDocuments_App(NULL);
1003 iForEach(ObjectList, i, docs) {
1004 memorySize += memorySize_History(history_DocumentWidget(i.object));
1005 }
1006 init_ObjectListIterator(&i, docs);
1007 iBool wasPruned = iFalse;
1008 while (memorySize > limit) {
1009 iDocumentWidget *doc = i.object;
1010 const size_t pruned = pruneLeastImportantMemory_History(history_DocumentWidget(doc));
1011 if (pruned) {
1012 memorySize -= pruned;
1013 wasPruned = iTrue;
1014 }
1015 next_ObjectListIterator(&i);
1016 if (!i.value) {
1017 if (!wasPruned) break;
1018 wasPruned = iFalse;
1019 init_ObjectListIterator(&i, docs);
1020 }
1021 }
1022 iRelease(docs);
1023}
1024
982iLocalDef iBool isWaitingAllowed_App_(iApp *d) { 1025iLocalDef iBool isWaitingAllowed_App_(iApp *d) {
983 if (!isEmpty_Periodic(&d->periodic)) { 1026 if (!isEmpty_Periodic(&d->periodic)) {
984 return iFalse; 1027 return iFalse;
@@ -1049,6 +1092,13 @@ void processEvents_App(enum iAppEventMode eventMode) {
1049 postRefresh_App(); 1092 postRefresh_App();
1050 break; 1093 break;
1051 case SDL_APP_WILLENTERBACKGROUND: 1094 case SDL_APP_WILLENTERBACKGROUND:
1095#if defined (iPlatformAppleMobile)
1096 updateNowPlayingInfo_iOS();
1097#endif
1098 setFreezeDraw_Window(d->window, iTrue);
1099 savePrefs_App_(d);
1100 saveState_App_(d);
1101 break;
1052 case SDL_APP_TERMINATING: 1102 case SDL_APP_TERMINATING:
1053 setFreezeDraw_Window(d->window, iTrue); 1103 setFreezeDraw_Window(d->window, iTrue);
1054 savePrefs_App_(d); 1104 savePrefs_App_(d);
@@ -1149,6 +1199,45 @@ void processEvents_App(enum iAppEventMode eventMode) {
1149 ev.wheel.x = -ev.wheel.x; 1199 ev.wheel.x = -ev.wheel.x;
1150#endif 1200#endif
1151 } 1201 }
1202#if defined (LAGRANGE_ENABLE_MOUSE_TOUCH_EMULATION)
1203 /* Convert mouse events to finger events to test the touch handling. */ {
1204 static float xPrev = 0.0f;
1205 static float yPrev = 0.0f;
1206 if (ev.type == SDL_MOUSEBUTTONDOWN || ev.type == SDL_MOUSEBUTTONUP) {
1207 const float xf = (d->window->pixelRatio * ev.button.x) / (float) d->window->size.x;
1208 const float yf = (d->window->pixelRatio * ev.button.y) / (float) d->window->size.y;
1209 ev.type = (ev.type == SDL_MOUSEBUTTONDOWN ? SDL_FINGERDOWN : SDL_FINGERUP);
1210 ev.tfinger.x = xf;
1211 ev.tfinger.y = yf;
1212 ev.tfinger.dx = xf - xPrev;
1213 ev.tfinger.dy = yf - yPrev;
1214 xPrev = xf;
1215 yPrev = yf;
1216 ev.tfinger.fingerId = 0x1234;
1217 ev.tfinger.pressure = 1.0f;
1218 ev.tfinger.timestamp = SDL_GetTicks();
1219 ev.tfinger.touchId = SDL_TOUCH_MOUSEID;
1220 }
1221 else if (ev.type == SDL_MOUSEMOTION) {
1222 if (~ev.motion.state & SDL_BUTTON(SDL_BUTTON_LEFT)) {
1223 continue; /* only when pressing a button */
1224 }
1225 const float xf = (d->window->pixelRatio * ev.motion.x) / (float) d->window->size.x;
1226 const float yf = (d->window->pixelRatio * ev.motion.y) / (float) d->window->size.y;
1227 ev.type = SDL_FINGERMOTION;
1228 ev.tfinger.x = xf;
1229 ev.tfinger.y = yf;
1230 ev.tfinger.dx = xf - xPrev;
1231 ev.tfinger.dy = yf - yPrev;
1232 xPrev = xf;
1233 yPrev = yf;
1234 ev.tfinger.fingerId = 0x1234;
1235 ev.tfinger.pressure = 1.0f;
1236 ev.tfinger.timestamp = SDL_GetTicks();
1237 ev.tfinger.touchId = SDL_TOUCH_MOUSEID;
1238 }
1239 }
1240#endif
1152 iBool wasUsed = processEvent_Window(d->window, &ev); 1241 iBool wasUsed = processEvent_Window(d->window, &ev);
1153 if (!wasUsed) { 1242 if (!wasUsed) {
1154 /* There may be a key bindings for this. */ 1243 /* There may be a key bindings for this. */
@@ -1565,7 +1654,9 @@ static iBool handlePrefsCommands_(iWidget *d, const char *cmd) {
1565 postCommandf_App("searchurl address:%s", 1654 postCommandf_App("searchurl address:%s",
1566 cstrText_InputWidget(findChild_Widget(d, "prefs.searchurl"))); 1655 cstrText_InputWidget(findChild_Widget(d, "prefs.searchurl")));
1567 postCommandf_App("cachesize.set arg:%d", 1656 postCommandf_App("cachesize.set arg:%d",
1568 toInt_String(text_InputWidget(findChild_Widget(d, "prefs.cachesize")))); 1657 toInt_String(text_InputWidget(findChild_Widget(d, "prefs.cachesize"))));
1658 postCommandf_App("memorysize.set arg:%d",
1659 toInt_String(text_InputWidget(findChild_Widget(d, "prefs.memorysize"))));
1569 postCommandf_App("ca.file path:%s", 1660 postCommandf_App("ca.file path:%s",
1570 cstrText_InputWidget(findChild_Widget(d, "prefs.ca.file"))); 1661 cstrText_InputWidget(findChild_Widget(d, "prefs.ca.file")));
1571 postCommandf_App("ca.path path:%s", 1662 postCommandf_App("ca.path path:%s",
@@ -1978,7 +2069,7 @@ iBool handleCommand_App(const char *cmd) {
1978 else if (equal_Command(cmd, "hidetoolbarscroll")) { 2069 else if (equal_Command(cmd, "hidetoolbarscroll")) {
1979 d->prefs.hideToolbarOnScroll = arg_Command(cmd); 2070 d->prefs.hideToolbarOnScroll = arg_Command(cmd);
1980 if (!d->prefs.hideToolbarOnScroll) { 2071 if (!d->prefs.hideToolbarOnScroll) {
1981 showToolbars_Root(get_Root(), iTrue); 2072 showToolbar_Root(get_Root(), iTrue);
1982 } 2073 }
1983 return iTrue; 2074 return iTrue;
1984 } 2075 }
@@ -2127,6 +2218,13 @@ iBool handleCommand_App(const char *cmd) {
2127 } 2218 }
2128 return iTrue; 2219 return iTrue;
2129 } 2220 }
2221 else if (equal_Command(cmd, "memorysize.set")) {
2222 d->prefs.maxMemorySize = arg_Command(cmd);
2223 if (d->prefs.maxMemorySize <= 0) {
2224 d->prefs.maxMemorySize = 0;
2225 }
2226 return iTrue;
2227 }
2130 else if (equal_Command(cmd, "searchurl")) { 2228 else if (equal_Command(cmd, "searchurl")) {
2131 iString *url = &d->prefs.searchUrl; 2229 iString *url = &d->prefs.searchUrl;
2132 setCStr_String(url, suffixPtr_Command(cmd, "address")); 2230 setCStr_String(url, suffixPtr_Command(cmd, "address"));
@@ -2188,7 +2286,8 @@ iBool handleCommand_App(const char *cmd) {
2188 } 2286 }
2189 else if (equal_Command(cmd, "open")) { 2287 else if (equal_Command(cmd, "open")) {
2190 iString *url = collectNewCStr_String(suffixPtr_Command(cmd, "url")); 2288 iString *url = collectNewCStr_String(suffixPtr_Command(cmd, "url"));
2191 const iBool noProxy = argLabel_Command(cmd, "noproxy"); 2289 const iBool noProxy = argLabel_Command(cmd, "noproxy") != 0;
2290 const iBool fromSidebar = argLabel_Command(cmd, "fromsidebar") != 0;
2192 iUrl parts; 2291 iUrl parts;
2193 init_Url(&parts, url); 2292 init_Url(&parts, url);
2194 if (argLabel_Command(cmd, "default") || equalCase_Rangecc(parts.scheme, "mailto") || 2293 if (argLabel_Command(cmd, "default") || equalCase_Rangecc(parts.scheme, "mailto") ||
@@ -2239,7 +2338,9 @@ iBool handleCommand_App(const char *cmd) {
2239 else { 2338 else {
2240 urlEncodePath_String(url); 2339 urlEncodePath_String(url);
2241 } 2340 }
2242 setUrlFromCache_DocumentWidget(doc, url, isHistory); 2341 setUrlFlags_DocumentWidget(doc, url,
2342 (isHistory ? useCachedContentIfAvailable_DocumentWidgetSetUrlFlag : 0) |
2343 (fromSidebar ? openedFromSidebar_DocumentWidgetSetUrlFlag : 0));
2243 /* Optionally, jump to a text in the document. This will only work if the document 2344 /* Optionally, jump to a text in the document. This will only work if the document
2244 is already available, e.g., it's from "about:" or restored from cache. */ 2345 is already available, e.g., it's from "about:" or restored from cache. */
2245 const iRangecc gotoHeading = range_Command(cmd, "gotoheading"); 2346 const iRangecc gotoHeading = range_Command(cmd, "gotoheading");
@@ -2254,6 +2355,36 @@ iBool handleCommand_App(const char *cmd) {
2254 } 2355 }
2255 setCurrent_Root(oldRoot); 2356 setCurrent_Root(oldRoot);
2256 } 2357 }
2358 else if (equal_Command(cmd, "file.open")) {
2359 const char *path = suffixPtr_Command(cmd, "path");
2360 if (path) {
2361 postCommandf_App("open temp:%d url:%s",
2362 argLabel_Command(cmd, "temp"),
2363 makeFileUrl_CStr(path));
2364 return iTrue;
2365 }
2366#if defined (iPlatformAppleMobile)
2367 pickFileForOpening_iOS();
2368#endif
2369 return iTrue;
2370 }
2371 else if (equal_Command(cmd, "file.delete")) {
2372 const char *path = suffixPtr_Command(cmd, "path");
2373 if (argLabel_Command(cmd, "confirm")) {
2374 makeQuestion_Widget(
2375 uiHeading_ColorEscape "${heading.file.delete}",
2376 format_CStr("${dlg.file.delete.confirm}\n%s", path),
2377 (iMenuItem[]){
2378 { "${cancel}", 0, 0, NULL },
2379 { uiTextCaution_ColorEscape "${dlg.file.delete}", 0, 0,
2380 format_CStr("!file.delete path:%s", path) } },
2381 2);
2382 }
2383 else {
2384 remove(path);
2385 }
2386 return iTrue;
2387 }
2257 else if (equal_Command(cmd, "document.request.cancelled")) { 2388 else if (equal_Command(cmd, "document.request.cancelled")) {
2258 /* TODO: How should cancelled requests be treated in the history? */ 2389 /* TODO: How should cancelled requests be treated in the history? */
2259#if 0 2390#if 0
@@ -2405,6 +2536,8 @@ iBool handleCommand_App(const char *cmd) {
2405 iTrue); 2536 iTrue);
2406 setText_InputWidget(findChild_Widget(dlg, "prefs.cachesize"), 2537 setText_InputWidget(findChild_Widget(dlg, "prefs.cachesize"),
2407 collectNewFormat_String("%d", d->prefs.maxCacheSize)); 2538 collectNewFormat_String("%d", d->prefs.maxCacheSize));
2539 setText_InputWidget(findChild_Widget(dlg, "prefs.memorysize"),
2540 collectNewFormat_String("%d", d->prefs.maxMemorySize));
2408 setToggle_Widget(findChild_Widget(dlg, "prefs.decodeurls"), d->prefs.decodeUserVisibleURLs); 2541 setToggle_Widget(findChild_Widget(dlg, "prefs.decodeurls"), d->prefs.decodeUserVisibleURLs);
2409 setText_InputWidget(findChild_Widget(dlg, "prefs.searchurl"), &d->prefs.searchUrl); 2542 setText_InputWidget(findChild_Widget(dlg, "prefs.searchurl"), &d->prefs.searchUrl);
2410 setText_InputWidget(findChild_Widget(dlg, "prefs.ca.file"), &d->prefs.caFile); 2543 setText_InputWidget(findChild_Widget(dlg, "prefs.ca.file"), &d->prefs.caFile);
@@ -2491,11 +2624,16 @@ iBool handleCommand_App(const char *cmd) {
2491 return iTrue; 2624 return iTrue;
2492 } 2625 }
2493 else if (equal_Command(cmd, "feeds.update.started")) { 2626 else if (equal_Command(cmd, "feeds.update.started")) {
2494 showCollapsed_Widget(findWidget_App("feeds.progress"), iTrue); 2627 iAnyObject *prog = findWidget_Root("feeds.progress");
2628 const iWidget *navBar = findWidget_Root("navbar");
2629 updateTextAndResizeWidthCStr_LabelWidget(
2630 prog, flags_Widget(navBar) & tight_WidgetFlag || deviceType_App() == phone_AppDeviceType ?
2631 "\u2605" : "\u2605 ${status.feeds}");
2632 showCollapsed_Widget(prog, iTrue);
2495 return iFalse; 2633 return iFalse;
2496 } 2634 }
2497 else if (equal_Command(cmd, "feeds.update.finished")) { 2635 else if (equal_Command(cmd, "feeds.update.finished")) {
2498 showCollapsed_Widget(findWidget_App("feeds.progress"), iFalse); 2636 showCollapsed_Widget(findWidget_Root("feeds.progress"), iFalse);
2499 refreshFinished_Feeds(); 2637 refreshFinished_Feeds();
2500 postRefresh_App(); 2638 postRefresh_App();
2501 return iFalse; 2639 return iFalse;