diff options
Diffstat (limited to 'src/app.c')
-rw-r--r-- | src/app.c | 101 |
1 files changed, 72 insertions, 29 deletions
@@ -168,6 +168,7 @@ const iString *dateStr_(const iDate *date) { | |||
168 | 168 | ||
169 | static iString *serializePrefs_App_(const iApp *d) { | 169 | static iString *serializePrefs_App_(const iApp *d) { |
170 | iString *str = new_String(); | 170 | iString *str = new_String(); |
171 | setCurrent_Root(d->window->roots[0]); /* TODO: How about the other? */ | ||
171 | const iSidebarWidget *sidebar = findWidget_App("sidebar"); | 172 | const iSidebarWidget *sidebar = findWidget_App("sidebar"); |
172 | const iSidebarWidget *sidebar2 = findWidget_App("sidebar2"); | 173 | const iSidebarWidget *sidebar2 = findWidget_App("sidebar2"); |
173 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) | 174 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) |
@@ -374,6 +375,11 @@ static void savePrefs_App_(const iApp *d) { | |||
374 | static const char *magicState_App_ = "lgL1"; | 375 | static const char *magicState_App_ = "lgL1"; |
375 | static const char *magicTabDocument_App_ = "tabd"; | 376 | static const char *magicTabDocument_App_ = "tabd"; |
376 | 377 | ||
378 | enum iDocumentStateFlag { | ||
379 | current_DocumentStateFlag = iBit(1), | ||
380 | rootIndex1_DocumentStateFlag = iBit(2) | ||
381 | }; | ||
382 | |||
377 | static iBool loadState_App_(iApp *d) { | 383 | static iBool loadState_App_(iApp *d) { |
378 | iUnused(d); | 384 | iUnused(d); |
379 | const char *oldPath = concatPath_CStr(dataDir_App_(), oldStateFileName_App_); | 385 | const char *oldPath = concatPath_CStr(dataDir_App_(), oldStateFileName_App_); |
@@ -392,17 +398,18 @@ static iBool loadState_App_(iApp *d) { | |||
392 | printf("%s: unsupported version\n", cstr_String(path_File(f))); | 398 | printf("%s: unsupported version\n", cstr_String(path_File(f))); |
393 | return iFalse; | 399 | return iFalse; |
394 | } | 400 | } |
395 | setCurrent_Root(&d->window->root); | ||
396 | setVersion_Stream(stream_File(f), version); | 401 | setVersion_Stream(stream_File(f), version); |
397 | iDocumentWidget *doc = document_App(); | 402 | iDocumentWidget *doc = document_App(); /* first one is always from root 0 */ |
398 | iDocumentWidget *current = NULL; | 403 | iDocumentWidget *current = NULL; |
399 | while (!atEnd_File(f)) { | 404 | while (!atEnd_File(f)) { |
400 | readData_File(f, 4, magic); | 405 | readData_File(f, 4, magic); |
401 | if (!memcmp(magic, magicTabDocument_App_, 4)) { | 406 | if (!memcmp(magic, magicTabDocument_App_, 4)) { |
407 | const int8_t flags = read8_File(f); | ||
402 | if (!doc) { | 408 | if (!doc) { |
409 | setCurrent_Root(d->window->roots[flags & rootIndex1_DocumentStateFlag ? 1 : 0]); | ||
403 | doc = newTab_App(NULL, iFalse /* no switching */); | 410 | doc = newTab_App(NULL, iFalse /* no switching */); |
404 | } | 411 | } |
405 | if (read8_File(f)) { | 412 | if (flags & current_DocumentStateFlag) { |
406 | current = doc; | 413 | current = doc; |
407 | } | 414 | } |
408 | deserializeState_DocumentWidget(doc, stream_File(f)); | 415 | deserializeState_DocumentWidget(doc, stream_File(f)); |
@@ -421,17 +428,6 @@ static iBool loadState_App_(iApp *d) { | |||
421 | return iFalse; | 428 | return iFalse; |
422 | } | 429 | } |
423 | 430 | ||
424 | iObjectList *listDocuments_App(void) { | ||
425 | iObjectList *docs = new_ObjectList(); | ||
426 | const iWidget *tabs = findWidget_App("doctabs"); | ||
427 | iForEach(ObjectList, i, children_Widget(findChild_Widget(tabs, "tabs.pages"))) { | ||
428 | if (isInstance_Object(i.object, &Class_DocumentWidget)) { | ||
429 | pushBack_ObjectList(docs, i.object); | ||
430 | } | ||
431 | } | ||
432 | return docs; | ||
433 | } | ||
434 | |||
435 | static void saveState_App_(const iApp *d) { | 431 | static void saveState_App_(const iApp *d) { |
436 | iUnused(d); | 432 | iUnused(d); |
437 | trimCache_App(); | 433 | trimCache_App(); |
@@ -439,14 +435,17 @@ static void saveState_App_(const iApp *d) { | |||
439 | if (open_File(f, writeOnly_FileMode)) { | 435 | if (open_File(f, writeOnly_FileMode)) { |
440 | writeData_File(f, magicState_App_, 4); | 436 | writeData_File(f, magicState_App_, 4); |
441 | writeU32_File(f, latest_FileVersion); /* version */ | 437 | writeU32_File(f, latest_FileVersion); /* version */ |
442 | setCurrent_Root(&d->window->root); | 438 | iConstForEach(ObjectList, i, iClob(listDocuments_App(NULL))) { |
443 | iConstForEach(ObjectList, i, iClob(listDocuments_App())) { | ||
444 | iAssert(isInstance_Object(i.object, &Class_DocumentWidget)); | 439 | iAssert(isInstance_Object(i.object, &Class_DocumentWidget)); |
440 | const iWidget *widget = constAs_Widget(i.object); | ||
445 | writeData_File(f, magicTabDocument_App_, 4); | 441 | writeData_File(f, magicTabDocument_App_, 4); |
446 | write8_File(f, document_App() == i.object ? 1 : 0); | 442 | int8_t flags = (document_Root(widget->root) == i.object ? current_DocumentStateFlag : 0); |
443 | if (widget->root == d->window->roots[1]) { | ||
444 | flags |= rootIndex1_DocumentStateFlag; | ||
445 | } | ||
446 | write8_File(f, flags); | ||
447 | serializeState_DocumentWidget(i.object, stream_File(f)); | 447 | serializeState_DocumentWidget(i.object, stream_File(f)); |
448 | } | 448 | } |
449 | setCurrent_Root(NULL); | ||
450 | } | 449 | } |
451 | else { | 450 | else { |
452 | fprintf(stderr, "[App] failed to save state: %s\n", strerror(errno)); | 451 | fprintf(stderr, "[App] failed to save state: %s\n", strerror(errno)); |
@@ -823,7 +822,7 @@ const iString *debugInfo_App(void) { | |||
823 | iString *msg = collectNew_String(); | 822 | iString *msg = collectNew_String(); |
824 | format_String(msg, "# Debug information\n"); | 823 | format_String(msg, "# Debug information\n"); |
825 | appendFormat_String(msg, "## Documents\n"); | 824 | appendFormat_String(msg, "## Documents\n"); |
826 | iForEach(ObjectList, k, iClob(listDocuments_App())) { | 825 | iForEach(ObjectList, k, iClob(listDocuments_App(NULL))) { |
827 | iDocumentWidget *doc = k.object; | 826 | iDocumentWidget *doc = k.object; |
828 | appendFormat_String(msg, "### Tab %zu: %s\n", | 827 | appendFormat_String(msg, "### Tab %zu: %s\n", |
829 | childIndex_Widget(constAs_Widget(doc)->parent, k.object), | 828 | childIndex_Widget(constAs_Widget(doc)->parent, k.object), |
@@ -849,7 +848,7 @@ const iString *debugInfo_App(void) { | |||
849 | } | 848 | } |
850 | 849 | ||
851 | static void clearCache_App_(void) { | 850 | static void clearCache_App_(void) { |
852 | iForEach(ObjectList, i, iClob(listDocuments_App())) { | 851 | iForEach(ObjectList, i, iClob(listDocuments_App(NULL))) { |
853 | clearCache_History(history_DocumentWidget(i.object)); | 852 | clearCache_History(history_DocumentWidget(i.object)); |
854 | } | 853 | } |
855 | } | 854 | } |
@@ -858,7 +857,7 @@ void trimCache_App(void) { | |||
858 | iApp *d = &app_; | 857 | iApp *d = &app_; |
859 | size_t cacheSize = 0; | 858 | size_t cacheSize = 0; |
860 | const size_t limit = d->prefs.maxCacheSize * 1000000; | 859 | const size_t limit = d->prefs.maxCacheSize * 1000000; |
861 | iObjectList *docs = listDocuments_App(); | 860 | iObjectList *docs = listDocuments_App(NULL); |
862 | iForEach(ObjectList, i, docs) { | 861 | iForEach(ObjectList, i, docs) { |
863 | cacheSize += cacheSize_History(history_DocumentWidget(i.object)); | 862 | cacheSize += cacheSize_History(history_DocumentWidget(i.object)); |
864 | } | 863 | } |
@@ -1051,7 +1050,12 @@ void processEvents_App(enum iAppEventMode eventMode) { | |||
1051 | handleCommand_MacOS(command_UserEvent(&ev)); | 1050 | handleCommand_MacOS(command_UserEvent(&ev)); |
1052 | #endif | 1051 | #endif |
1053 | if (isMetricsChange_UserEvent(&ev)) { | 1052 | if (isMetricsChange_UserEvent(&ev)) { |
1054 | arrange_Widget(d->window->root.widget); | 1053 | iForIndices(i, d->window->roots) { |
1054 | iRoot *root = d->window->roots[i]; | ||
1055 | if (root) { | ||
1056 | arrange_Widget(root->widget); | ||
1057 | } | ||
1058 | } | ||
1055 | } | 1059 | } |
1056 | if (!wasUsed) { | 1060 | if (!wasUsed) { |
1057 | /* No widget handled the command, so we'll do it. */ | 1061 | /* No widget handled the command, so we'll do it. */ |
@@ -1087,10 +1091,10 @@ static void runTickers_App_(iApp *d) { | |||
1087 | iSortedArray *pending = copy_SortedArray(&d->tickers); | 1091 | iSortedArray *pending = copy_SortedArray(&d->tickers); |
1088 | clear_SortedArray(&d->tickers); | 1092 | clear_SortedArray(&d->tickers); |
1089 | postRefresh_App(); | 1093 | postRefresh_App(); |
1090 | setCurrent_Root(&d->window->root); /* TODO: Each ticker has its own root. */ | ||
1091 | iConstForEach(Array, i, &pending->values) { | 1094 | iConstForEach(Array, i, &pending->values) { |
1092 | const iTicker *ticker = i.value; | 1095 | const iTicker *ticker = i.value; |
1093 | if (ticker->callback) { | 1096 | if (ticker->callback) { |
1097 | setCurrent_Root(findRoot_Window(d->window, ticker->context)); | ||
1094 | ticker->callback(ticker->context); | 1098 | ticker->callback(ticker->context); |
1095 | } | 1099 | } |
1096 | } | 1100 | } |
@@ -1120,7 +1124,11 @@ static int resizeWatcher_(void *user, SDL_Event *event) { | |||
1120 | } | 1124 | } |
1121 | 1125 | ||
1122 | static int run_App_(iApp *d) { | 1126 | static int run_App_(iApp *d) { |
1123 | arrange_Widget(findWidget_App("root")); | 1127 | iForIndices(i, d->window->roots) { |
1128 | if (d->window->roots[i]) { | ||
1129 | arrange_Widget(d->window->roots[i]->widget); | ||
1130 | } | ||
1131 | } | ||
1124 | d->isRunning = iTrue; | 1132 | d->isRunning = iTrue; |
1125 | SDL_EventState(SDL_DROPFILE, SDL_ENABLE); /* open files via drag'n'drop */ | 1133 | SDL_EventState(SDL_DROPFILE, SDL_ENABLE); /* open files via drag'n'drop */ |
1126 | #if defined (iPlatformDesktop) | 1134 | #if defined (iPlatformDesktop) |
@@ -1139,7 +1147,12 @@ static int run_App_(iApp *d) { | |||
1139 | 1147 | ||
1140 | void refresh_App(void) { | 1148 | void refresh_App(void) { |
1141 | iApp *d = &app_; | 1149 | iApp *d = &app_; |
1142 | destroyPending_Root(&d->window->root); | 1150 | iForIndices(i, d->window->roots) { |
1151 | iRoot *root = d->window->roots[i]; | ||
1152 | if (root) { | ||
1153 | destroyPending_Root(root); | ||
1154 | } | ||
1155 | } | ||
1143 | #if defined (LAGRANGE_ENABLE_IDLE_SLEEP) | 1156 | #if defined (LAGRANGE_ENABLE_IDLE_SLEEP) |
1144 | if (d->warmupFrames == 0 && d->isIdling) { | 1157 | if (d->warmupFrames == 0 && d->isIdling) { |
1145 | return; | 1158 | return; |
@@ -1270,7 +1283,16 @@ void postCommandf_App(const char *command, ...) { | |||
1270 | 1283 | ||
1271 | iAny *findWidget_App(const char *id) { | 1284 | iAny *findWidget_App(const char *id) { |
1272 | if (!*id) return NULL; | 1285 | if (!*id) return NULL; |
1273 | return findChild_Widget(app_.window->root.widget, id); | 1286 | iForIndices(i, app_.window->roots) { |
1287 | iRoot *root = app_.window->roots[i]; | ||
1288 | if (root) { | ||
1289 | iAny *found = findChild_Widget(root->widget, id); | ||
1290 | if (found) { | ||
1291 | return found; | ||
1292 | } | ||
1293 | } | ||
1294 | } | ||
1295 | return NULL; | ||
1274 | } | 1296 | } |
1275 | 1297 | ||
1276 | void addTicker_App(iTickerFunc ticker, iAny *context) { | 1298 | void addTicker_App(iTickerFunc ticker, iAny *context) { |
@@ -1438,8 +1460,12 @@ static iBool handlePrefsCommands_(iWidget *d, const char *cmd) { | |||
1438 | return iFalse; | 1460 | return iFalse; |
1439 | } | 1461 | } |
1440 | 1462 | ||
1463 | iDocumentWidget *document_Root(iRoot *d) { | ||
1464 | return iConstCast(iDocumentWidget *, currentTabPage_Widget(findChild_Widget(d->widget, "doctabs"))); | ||
1465 | } | ||
1466 | |||
1441 | iDocumentWidget *document_App(void) { | 1467 | iDocumentWidget *document_App(void) { |
1442 | return iConstCast(iDocumentWidget *, currentTabPage_Widget(findWidget_App("doctabs"))); | 1468 | return document_Root(get_Root()); |
1443 | } | 1469 | } |
1444 | 1470 | ||
1445 | iDocumentWidget *document_Command(const char *cmd) { | 1471 | iDocumentWidget *document_Command(const char *cmd) { |
@@ -2128,7 +2154,7 @@ iBool handleCommand_App(const char *cmd) { | |||
2128 | else if (equal_Command(cmd, "ident.import")) { | 2154 | else if (equal_Command(cmd, "ident.import")) { |
2129 | iCertImportWidget *imp = new_CertImportWidget(); | 2155 | iCertImportWidget *imp = new_CertImportWidget(); |
2130 | setPageContent_CertImportWidget(imp, sourceContent_DocumentWidget(document_App())); | 2156 | setPageContent_CertImportWidget(imp, sourceContent_DocumentWidget(document_App())); |
2131 | addChild_Widget(d->window->root.widget, iClob(imp)); | 2157 | addChild_Widget(get_Root()->widget, iClob(imp)); |
2132 | finalizeSheet_Widget(as_Widget(imp)); | 2158 | finalizeSheet_Widget(as_Widget(imp)); |
2133 | postRefresh_App(); | 2159 | postRefresh_App(); |
2134 | return iTrue; | 2160 | return iTrue; |
@@ -2173,7 +2199,7 @@ iBool handleCommand_App(const char *cmd) { | |||
2173 | iProcessId pid = argLabel_Command(cmd, "pid"); | 2199 | iProcessId pid = argLabel_Command(cmd, "pid"); |
2174 | if (pid) { | 2200 | if (pid) { |
2175 | iString *urls = collectNew_String(); | 2201 | iString *urls = collectNew_String(); |
2176 | iConstForEach(ObjectList, i, iClob(listDocuments_App())) { | 2202 | iConstForEach(ObjectList, i, iClob(listDocuments_App(NULL))) { |
2177 | append_String(urls, url_DocumentWidget(i.object)); | 2203 | append_String(urls, url_DocumentWidget(i.object)); |
2178 | appendCStr_String(urls, "\n"); | 2204 | appendCStr_String(urls, "\n"); |
2179 | } | 2205 | } |
@@ -2258,3 +2284,20 @@ void revealPath_App(const iString *path) { | |||
2258 | iAssert(0 /* File revealing not implemented on this platform */); | 2284 | iAssert(0 /* File revealing not implemented on this platform */); |
2259 | #endif | 2285 | #endif |
2260 | } | 2286 | } |
2287 | |||
2288 | iObjectList *listDocuments_App(const iRoot *rootOrNull) { | ||
2289 | iWindow *win = get_Window(); | ||
2290 | iObjectList *docs = new_ObjectList(); | ||
2291 | iForIndices(i, win->roots) { | ||
2292 | iRoot *root = win->roots[i]; | ||
2293 | if (!rootOrNull || root == rootOrNull) { | ||
2294 | const iWidget *tabs = findChild_Widget(root->widget, "doctabs"); | ||
2295 | iForEach(ObjectList, i, children_Widget(findChild_Widget(tabs, "tabs.pages"))) { | ||
2296 | if (isInstance_Object(i.object, &Class_DocumentWidget)) { | ||
2297 | pushBack_ObjectList(docs, i.object); | ||
2298 | } | ||
2299 | } | ||
2300 | } | ||
2301 | } | ||
2302 | return docs; | ||
2303 | } | ||