summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2022-02-19 08:15:43 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2022-02-19 08:15:43 +0200
commit1ef7170f2b1b8c48fababc112673afa17729033f (patch)
tree1339f42ec947a367de792a95886decfefa0cc87d
parentdd9add718c4a9a2b29cd38b05886f22877b89b35 (diff)
App: Save multiple window rectangles
-rw-r--r--src/app.c127
-rw-r--r--src/ui/root.c11
-rw-r--r--src/ui/root.h1
3 files changed, 92 insertions, 47 deletions
diff --git a/src/app.c b/src/app.c
index 850a9706..ec8b59b3 100644
--- a/src/app.c
+++ b/src/app.c
@@ -154,7 +154,8 @@ struct Impl_App {
154 /* Preferences: */ 154 /* Preferences: */
155 iBool commandEcho; /* --echo */ 155 iBool commandEcho; /* --echo */
156 iBool forceSoftwareRender; /* --sw */ 156 iBool forceSoftwareRender; /* --sw */
157 iRect initialWindowRect; 157 //iRect initialWindowRect;
158 iArray initialWindowRects; /* one per window */
158 iPrefs prefs; 159 iPrefs prefs;
159}; 160};
160 161
@@ -200,33 +201,43 @@ static iString *serializePrefs_App_(const iApp *d) {
200 appendFormat_String(str, "window.retain arg:%d\n", d->prefs.retainWindowSize); 201 appendFormat_String(str, "window.retain arg:%d\n", d->prefs.retainWindowSize);
201 if (d->prefs.retainWindowSize) { 202 if (d->prefs.retainWindowSize) {
202 int w, h, x, y; 203 int w, h, x, y;
203 x = d->window->place.normalRect.pos.x; 204 iConstForEach(PtrArray, i, &d->mainWindows) {
204 y = d->window->place.normalRect.pos.y; 205 const iMainWindow *win = i.ptr;
205 w = d->window->place.normalRect.size.x; 206 const size_t winIndex = index_PtrArrayConstIterator(&i);
206 h = d->window->place.normalRect.size.y; 207 x = win->place.normalRect.pos.x;
207 appendFormat_String(str, "window.setrect width:%d height:%d coord:%d %d\n", w, h, x, y); 208 y = win->place.normalRect.pos.y;
208 /* On macOS, maximization should be applied at creation time or the window will take 209 w = win->place.normalRect.size.x;
209 a moment to animate to its maximized size. */ 210 h = win->place.normalRect.size.y;
211 appendFormat_String(str,
212 "window.setrect index:%zu width:%d height:%d coord:%d %d\n",
213 winIndex,
214 w,
215 h,
216 x,
217 y);
218 /* On macOS, maximization should be applied at creation time or the window will take
219 a moment to animate to its maximized size. */
210#if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) 220#if defined (LAGRANGE_ENABLE_CUSTOM_FRAME)
211 if (snap_MainWindow(d->window)) { 221 if (snap_MainWindow(win)) {
212 if (snap_MainWindow(d->window) == maximized_WindowSnap) { 222 if (snap_MainWindow(win) == maximized_WindowSnap) {
213 appendFormat_String(str, "~window.maximize\n"); 223 appendFormat_String(str, "~window.maximize index:%zu\n", winIndex);
214 } 224 }
215 else if (~SDL_GetWindowFlags(d->window->base.win) & SDL_WINDOW_MINIMIZED) { 225 else if (~SDL_GetWindowFlags(win->base.win) & SDL_WINDOW_MINIMIZED) {
216 /* Save the actual visible window position, too, because snapped windows may 226 /* Save the actual visible window position, too, because snapped windows may
217 still be resized/moved without affecting normalRect. */ 227 still be resized/moved without affecting normalRect. */
218 SDL_GetWindowPosition(d->window->base.win, &x, &y); 228 SDL_GetWindowPosition(win->base.win, &x, &y);
219 SDL_GetWindowSize(d->window->base.win, &w, &h); 229 SDL_GetWindowSize(win->base.win, &w, &h);
220 appendFormat_String( 230 appendFormat_String(
221 str, "~window.setrect snap:%d width:%d height:%d coord:%d %d\n", 231 str, "~window.setrect index:%zu snap:%d width:%d height:%d coord:%d %d\n",
222 snap_MainWindow(d->window), w, h, x, y); 232 winIndex, snap_MainWindow(d->window), w, h, x, y);
233 }
223 } 234 }
224 }
225#elif !defined (iPlatformApple) 235#elif !defined (iPlatformApple)
226 if (snap_MainWindow(d->window) == maximized_WindowSnap) { 236 if (snap_MainWindow(win) == maximized_WindowSnap) {
227 appendFormat_String(str, "~window.maximize\n"); 237 appendFormat_String(str, "~window.maximize index:%zu\n", winIndex);
228 } 238 }
229#endif 239#endif
240 }
230 } 241 }
231 appendFormat_String(str, "uilang id:%s\n", cstr_String(&d->prefs.strings[uiLanguage_PrefsString])); 242 appendFormat_String(str, "uilang id:%s\n", cstr_String(&d->prefs.strings[uiLanguage_PrefsString]));
232 appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(as_Window(d->window))); 243 appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(as_Window(d->window)));
@@ -404,9 +415,14 @@ static void loadPrefs_App_(iApp *d) {
404 d->prefs.customFrame = arg_Command(cmd); 415 d->prefs.customFrame = arg_Command(cmd);
405 } 416 }
406 else if (equal_Command(cmd, "window.setrect") && !argLabel_Command(cmd, "snap")) { 417 else if (equal_Command(cmd, "window.setrect") && !argLabel_Command(cmd, "snap")) {
407 const iInt2 pos = coord_Command(cmd); 418 const int index = argLabel_Command(cmd, "index");
408 d->initialWindowRect = init_Rect( 419 const iInt2 pos = coord_Command(cmd);
420 iRect winRect = init_Rect(
409 pos.x, pos.y, argLabel_Command(cmd, "width"), argLabel_Command(cmd, "height")); 421 pos.x, pos.y, argLabel_Command(cmd, "width"), argLabel_Command(cmd, "height"));
422 if (index >= 0 && index < 100) {
423 resize_Array(&d->initialWindowRects, index + 1);
424 set_Array(&d->initialWindowRects, index, &winRect);
425 }
410 } 426 }
411 else if (equal_Command(cmd, "fontpack.disable")) { 427 else if (equal_Command(cmd, "fontpack.disable")) {
412 insert_StringSet(d->prefs.disabledFontPacks, 428 insert_StringSet(d->prefs.disabledFontPacks,
@@ -483,6 +499,28 @@ enum iWindowStateFlag {
483 current_WindowStateFlag = iBit(9), 499 current_WindowStateFlag = iBit(9),
484}; 500};
485 501
502static iRect initialWindowRect_App_(const iApp *d, size_t windowIndex) {
503 if (windowIndex < size_Array(&d->initialWindowRects)) {
504 return constValue_Array(&d->initialWindowRects, windowIndex, iRect);
505 }
506 /* The default window rectangle. */
507 iRect rect = init_Rect(-1, -1, 900, 560);
508#if defined (iPlatformMsys)
509 /* Must scale by UI scaling factor. */
510 mulfv_I2(&rect.size, desktopDPI_Win32());
511#endif
512#if defined (iPlatformLinux) && !defined (iPlatformAndroid)
513 /* Scale by the primary (?) monitor DPI. */
514 if (isRunningUnderWindowSystem_App()) {
515 float vdpi;
516 SDL_GetDisplayDPI(0, NULL, NULL, &vdpi);
517 const float factor = vdpi / 96.0f;
518 mulfv_I2(&rect.size, iMax(factor, 1.0f));
519 }
520#endif
521 return rect;
522}
523
486static iBool loadState_App_(iApp *d) { 524static iBool loadState_App_(iApp *d) {
487 iUnused(d); 525 iUnused(d);
488 const char *oldPath = concatPath_CStr(dataDir_App_(), oldStateFileName_App_); 526 const char *oldPath = concatPath_CStr(dataDir_App_(), oldStateFileName_App_);
@@ -525,7 +563,7 @@ static iBool loadState_App_(iApp *d) {
525 win = d->window; 563 win = d->window;
526 } 564 }
527 else { 565 else {
528 win = new_MainWindow(d->initialWindowRect); 566 win = new_MainWindow(initialWindowRect_App_(d, numWins - 1));
529 addWindow_App(win); 567 addWindow_App(win);
530 } 568 }
531 pushBack_Array(currentTabs, &(iCurrentTabs){ { NULL, NULL } }); 569 pushBack_Array(currentTabs, &(iCurrentTabs){ { NULL, NULL } });
@@ -819,6 +857,7 @@ static void init_App_(iApp *d, int argc, char **argv) {
819 d->isDarkSystemTheme = iTrue; /* will be updated by system later on, if supported */ 857 d->isDarkSystemTheme = iTrue; /* will be updated by system later on, if supported */
820 d->isSuspended = iFalse; 858 d->isSuspended = iFalse;
821 d->tempFilesPendingDeletion = new_StringSet(); 859 d->tempFilesPendingDeletion = new_StringSet();
860 init_Array(&d->initialWindowRects, sizeof(iRect));
822 init_CommandLine(&d->args, argc, argv); 861 init_CommandLine(&d->args, argc, argv);
823 /* Where was the app started from? We ask SDL first because the command line alone 862 /* Where was the app started from? We ask SDL first because the command line alone
824 cannot be relied on (behavior differs depending on OS). */ { 863 cannot be relied on (behavior differs depending on OS). */ {
@@ -953,20 +992,6 @@ static void init_App_(iApp *d, int argc, char **argv) {
953 d->elapsedSinceLastTicker = 0; 992 d->elapsedSinceLastTicker = 0;
954 d->commandEcho = iClob(checkArgument_CommandLine(&d->args, "echo;E")) != NULL; 993 d->commandEcho = iClob(checkArgument_CommandLine(&d->args, "echo;E")) != NULL;
955 d->forceSoftwareRender = iClob(checkArgument_CommandLine(&d->args, "sw")) != NULL; 994 d->forceSoftwareRender = iClob(checkArgument_CommandLine(&d->args, "sw")) != NULL;
956 d->initialWindowRect = init_Rect(-1, -1, 900, 560);
957#if defined (iPlatformMsys)
958 /* Must scale by UI scaling factor. */
959 mulfv_I2(&d->initialWindowRect.size, desktopDPI_Win32());
960#endif
961#if defined (iPlatformLinux) && !defined (iPlatformAndroid)
962 /* Scale by the primary (?) monitor DPI. */
963 if (isRunningUnderWindowSystem_App()) {
964 float vdpi;
965 SDL_GetDisplayDPI(0, NULL, NULL, &vdpi);
966 const float factor = vdpi / 96.0f;
967 mulfv_I2(&d->initialWindowRect.size, iMax(factor, 1.0f));
968 }
969#endif
970 init_Prefs(&d->prefs); 995 init_Prefs(&d->prefs);
971 init_SiteSpec(dataDir_App_()); 996 init_SiteSpec(dataDir_App_());
972 setCStr_String(&d->prefs.strings[downloadDir_PrefsString], downloadDir_App_()); 997 setCStr_String(&d->prefs.strings[downloadDir_PrefsString], downloadDir_App_());
@@ -988,22 +1013,29 @@ static void init_App_(iApp *d, int argc, char **argv) {
988 init_Fonts(dataDir_App_()); 1013 init_Fonts(dataDir_App_());
989 loadPalette_Color(dataDir_App_()); 1014 loadPalette_Color(dataDir_App_());
990 setThemePalette_Color(d->prefs.theme); /* default UI colors */ 1015 setThemePalette_Color(d->prefs.theme); /* default UI colors */
991 loadPrefs_App_(d); 1016 /* Initial window rectangle of the first window. */ {
1017 iAssert(isEmpty_Array(&d->initialWindowRects));
1018 const iRect winRect = initialWindowRect_App_(d, 0); /* calculated */
1019 resize_Array(&d->initialWindowRects, 1);
1020 set_Array(&d->initialWindowRects, 0, &winRect);
1021 }
1022 loadPrefs_App_(d);
992 updateActive_Fonts(); 1023 updateActive_Fonts();
993 load_Keys(dataDir_App_()); 1024 load_Keys(dataDir_App_());
1025 iRect *winRect0 = at_Array(&d->initialWindowRects, 0);
994 /* See if the user wants to override the window size. */ { 1026 /* See if the user wants to override the window size. */ {
995 iCommandLineArg *arg = iClob(checkArgument_CommandLine(&d->args, windowWidth_CommandLineOption)); 1027 iCommandLineArg *arg = iClob(checkArgument_CommandLine(&d->args, windowWidth_CommandLineOption));
996 if (arg) { 1028 if (arg) {
997 d->initialWindowRect.size.x = toInt_String(value_CommandLineArg(arg, 0)); 1029 winRect0->size.x = toInt_String(value_CommandLineArg(arg, 0));
998 } 1030 }
999 arg = iClob(checkArgument_CommandLine(&d->args, windowHeight_CommandLineOption)); 1031 arg = iClob(checkArgument_CommandLine(&d->args, windowHeight_CommandLineOption));
1000 if (arg) { 1032 if (arg) {
1001 d->initialWindowRect.size.y = toInt_String(value_CommandLineArg(arg, 0)); 1033 winRect0->size.y = toInt_String(value_CommandLineArg(arg, 0));
1002 } 1034 }
1003 } 1035 }
1004 init_PtrArray(&d->mainWindows); 1036 init_PtrArray(&d->mainWindows);
1005 init_PtrArray(&d->popupWindows); 1037 init_PtrArray(&d->popupWindows);
1006 d->window = new_MainWindow(d->initialWindowRect); 1038 d->window = new_MainWindow(*winRect0); /* first window is always created */
1007 addWindow_App(d->window); 1039 addWindow_App(d->window);
1008 load_Visited(d->visited, dataDir_App_()); 1040 load_Visited(d->visited, dataDir_App_());
1009 load_Bookmarks(d->bookmarks, dataDir_App_()); 1041 load_Bookmarks(d->bookmarks, dataDir_App_());
@@ -1101,7 +1133,8 @@ static void deinit_App(iApp *d) {
1101 /* Delete all temporary files created while running. */ 1133 /* Delete all temporary files created while running. */
1102 iConstForEach(StringSet, tmp, d->tempFilesPendingDeletion) { 1134 iConstForEach(StringSet, tmp, d->tempFilesPendingDeletion) {
1103 remove(cstr_String(tmp.value)); 1135 remove(cstr_String(tmp.value));
1104} 1136 }
1137 deinit_Array(&d->initialWindowRects);
1105 iRelease(d->tempFilesPendingDeletion); 1138 iRelease(d->tempFilesPendingDeletion);
1106} 1139}
1107 1140
@@ -3132,7 +3165,7 @@ iBool handleCommand_App(const char *cmd) {
3132 return iFalse; 3165 return iFalse;
3133 } 3166 }
3134 else if (equal_Command(cmd, "window.new")) { 3167 else if (equal_Command(cmd, "window.new")) {
3135 iMainWindow *newWin = new_MainWindow(moved_Rect(d->initialWindowRect, init_I2(30, 30))); 3168 iMainWindow *newWin = new_MainWindow(initialWindowRect_App_(d, numWindows_App()));
3136 addWindow_App(newWin); /* takes ownership */ 3169 addWindow_App(newWin); /* takes ownership */
3137 SDL_ShowWindow(newWin->base.win); 3170 SDL_ShowWindow(newWin->base.win);
3138 setCurrent_Window(newWin); 3171 setCurrent_Window(newWin);
diff --git a/src/ui/root.c b/src/ui/root.c
index eeb5956f..7e4b4863 100644
--- a/src/ui/root.c
+++ b/src/ui/root.c
@@ -468,6 +468,10 @@ static iBool handleRootCommands_(iWidget *root, const char *cmd) {
468 return iFalse; 468 return iFalse;
469 } 469 }
470 else if (equal_Command(cmd, "window.setrect")) { 470 else if (equal_Command(cmd, "window.setrect")) {
471 if (hasLabel_Command(cmd, "index") &&
472 argU32Label_Command(cmd, "index") != windowIndex_Root(root->root)) {
473 return iFalse;
474 }
471 const int snap = argLabel_Command(cmd, "snap"); 475 const int snap = argLabel_Command(cmd, "snap");
472 if (snap) { 476 if (snap) {
473 iMainWindow *window = get_MainWindow(); 477 iMainWindow *window = get_MainWindow();
@@ -1776,6 +1780,13 @@ void showToolbar_Root(iRoot *d, iBool show) {
1776 } 1780 }
1777} 1781}
1778 1782
1783size_t windowIndex_Root(const iRoot *d) {
1784 if (type_Window(d->window) == main_WindowType) {
1785 return windowIndex_App(as_MainWindow(d->window));
1786 }
1787 return iInvalidPos;
1788}
1789
1779iInt2 size_Root(const iRoot *d) { 1790iInt2 size_Root(const iRoot *d) {
1780 return d && d->widget ? d->widget->rect.size : zero_I2(); 1791 return d && d->widget ? d->widget->rect.size : zero_I2();
1781} 1792}
diff --git a/src/ui/root.h b/src/ui/root.h
index a81ebdf7..3b053c9e 100644
--- a/src/ui/root.h
+++ b/src/ui/root.h
@@ -47,6 +47,7 @@ void showOrHideNewTabButton_Root (iRoot *);
47 47
48void notifyVisualOffsetChange_Root (iRoot *); 48void notifyVisualOffsetChange_Root (iRoot *);
49 49
50size_t windowIndex_Root (const iRoot *);
50iInt2 size_Root (const iRoot *); 51iInt2 size_Root (const iRoot *);
51iRect rect_Root (const iRoot *); 52iRect rect_Root (const iRoot *);
52iRect safeRect_Root (const iRoot *); 53iRect safeRect_Root (const iRoot *);