diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-09-19 13:28:58 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-09-19 13:28:58 +0300 |
commit | 81007a2debffebc97c230cd810fb1bf10760180f (patch) | |
tree | 80639ed9d2723b397710cafd3de1a479ef400d02 | |
parent | b131ffbc42d66d7668844f12d7b24ddcf1a5c176 (diff) |
Refactoring Window to split off MainWindow
MainWindow represents (one of) the main windows of the app, while the basic Window will be a used for popups.
Only MainWindow supports split view modes.
-rw-r--r-- | src/app.c | 122 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 2 | ||||
-rw-r--r-- | src/ui/paint.c | 3 | ||||
-rw-r--r-- | src/ui/root.c | 10 | ||||
-rw-r--r-- | src/ui/uploadwidget.c | 2 | ||||
-rw-r--r-- | src/ui/util.c | 2 | ||||
-rw-r--r-- | src/ui/widget.c | 4 | ||||
-rw-r--r-- | src/ui/window.c | 557 | ||||
-rw-r--r-- | src/ui/window.h | 135 |
9 files changed, 462 insertions, 375 deletions
@@ -117,7 +117,7 @@ struct Impl_App { | |||
117 | iGmCerts * certs; | 117 | iGmCerts * certs; |
118 | iVisited * visited; | 118 | iVisited * visited; |
119 | iBookmarks * bookmarks; | 119 | iBookmarks * bookmarks; |
120 | iWindow * window; | 120 | iMainWindow *window; |
121 | iSortedArray tickers; /* per-frame callbacks, used for animations */ | 121 | iSortedArray tickers; /* per-frame callbacks, used for animations */ |
122 | uint32_t lastTickerTime; | 122 | uint32_t lastTickerTime; |
123 | uint32_t elapsedSinceLastTicker; | 123 | uint32_t elapsedSinceLastTicker; |
@@ -188,7 +188,7 @@ static iString *serializePrefs_App_(const iApp *d) { | |||
188 | /* On macOS, maximization should be applied at creation time or the window will take | 188 | /* On macOS, maximization should be applied at creation time or the window will take |
189 | a moment to animate to its maximized size. */ | 189 | a moment to animate to its maximized size. */ |
190 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) | 190 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) |
191 | if (snap_Window(d->window)) { | 191 | if (snap_MainWindow(d->window)) { |
192 | if (~SDL_GetWindowFlags(d->window->win) & SDL_WINDOW_MINIMIZED) { | 192 | if (~SDL_GetWindowFlags(d->window->win) & SDL_WINDOW_MINIMIZED) { |
193 | /* Save the actual visible window position, too, because snapped windows may | 193 | /* Save the actual visible window position, too, because snapped windows may |
194 | still be resized/moved without affecting normalRect. */ | 194 | still be resized/moved without affecting normalRect. */ |
@@ -196,17 +196,17 @@ static iString *serializePrefs_App_(const iApp *d) { | |||
196 | SDL_GetWindowSize(d->window->win, &w, &h); | 196 | SDL_GetWindowSize(d->window->win, &w, &h); |
197 | appendFormat_String( | 197 | appendFormat_String( |
198 | str, "~window.setrect snap:%d width:%d height:%d coord:%d %d\n", | 198 | str, "~window.setrect snap:%d width:%d height:%d coord:%d %d\n", |
199 | snap_Window(d->window), w, h, x, y); | 199 | snap_MainWindow(d->window), w, h, x, y); |
200 | } | 200 | } |
201 | } | 201 | } |
202 | #elif !defined (iPlatformApple) | 202 | #elif !defined (iPlatformApple) |
203 | if (snap_Window(d->window) == maximized_WindowSnap) { | 203 | if (snap_MainWindow(d->window) == maximized_WindowSnap) { |
204 | appendFormat_String(str, "~window.maximize\n"); | 204 | appendFormat_String(str, "~window.maximize\n"); |
205 | } | 205 | } |
206 | #endif | 206 | #endif |
207 | } | 207 | } |
208 | appendFormat_String(str, "uilang id:%s\n", cstr_String(&d->prefs.uiLanguage)); | 208 | appendFormat_String(str, "uilang id:%s\n", cstr_String(&d->prefs.uiLanguage)); |
209 | appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(d->window)); | 209 | appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(as_Window(d->window))); |
210 | appendFormat_String(str, "prefs.dialogtab arg:%d\n", d->prefs.dialogTab); | 210 | appendFormat_String(str, "prefs.dialogtab arg:%d\n", d->prefs.dialogTab); |
211 | appendFormat_String(str, "font.set arg:%d\n", d->prefs.font); | 211 | appendFormat_String(str, "font.set arg:%d\n", d->prefs.font); |
212 | appendFormat_String(str, "font.user path:%s\n", cstr_String(&d->prefs.symbolFontPath)); | 212 | appendFormat_String(str, "font.user path:%s\n", cstr_String(&d->prefs.symbolFontPath)); |
@@ -414,8 +414,8 @@ static iBool loadState_App_(iApp *d) { | |||
414 | const int splitMode = read32_File(f); | 414 | const int splitMode = read32_File(f); |
415 | const int keyRoot = read32_File(f); | 415 | const int keyRoot = read32_File(f); |
416 | d->window->pendingSplitMode = splitMode; | 416 | d->window->pendingSplitMode = splitMode; |
417 | setSplitMode_Window(d->window, splitMode | noEvents_WindowSplit); | 417 | setSplitMode_MainWindow(d->window, splitMode | noEvents_WindowSplit); |
418 | d->window->keyRoot = d->window->roots[keyRoot]; | 418 | d->window->base.keyRoot = d->window->base.roots[keyRoot]; |
419 | } | 419 | } |
420 | else if (!memcmp(magic, magicSidebar_App_, 4)) { | 420 | else if (!memcmp(magic, magicSidebar_App_, 4)) { |
421 | const uint16_t bits = readU16_File(f); | 421 | const uint16_t bits = readU16_File(f); |
@@ -426,7 +426,7 @@ static iBool loadState_App_(iApp *d) { | |||
426 | }; | 426 | }; |
427 | const uint8_t rootIndex = bits & 0xff; | 427 | const uint8_t rootIndex = bits & 0xff; |
428 | const uint8_t flags = bits >> 8; | 428 | const uint8_t flags = bits >> 8; |
429 | iRoot *root = d->window->roots[rootIndex]; | 429 | iRoot *root = d->window->base.roots[rootIndex]; |
430 | if (root) { | 430 | if (root) { |
431 | iSidebarWidget *sidebar = findChild_Widget(root->widget, "sidebar"); | 431 | iSidebarWidget *sidebar = findChild_Widget(root->widget, "sidebar"); |
432 | iSidebarWidget *sidebar2 = findChild_Widget(root->widget, "sidebar2"); | 432 | iSidebarWidget *sidebar2 = findChild_Widget(root->widget, "sidebar2"); |
@@ -443,10 +443,10 @@ static iBool loadState_App_(iApp *d) { | |||
443 | else if (!memcmp(magic, magicTabDocument_App_, 4)) { | 443 | else if (!memcmp(magic, magicTabDocument_App_, 4)) { |
444 | const int8_t flags = read8_File(f); | 444 | const int8_t flags = read8_File(f); |
445 | int rootIndex = flags & rootIndex1_DocumentStateFlag ? 1 : 0; | 445 | int rootIndex = flags & rootIndex1_DocumentStateFlag ? 1 : 0; |
446 | if (rootIndex > numRoots_Window(d->window) - 1) { | 446 | if (rootIndex > numRoots_Window(as_Window(d->window)) - 1) { |
447 | rootIndex = 0; | 447 | rootIndex = 0; |
448 | } | 448 | } |
449 | setCurrent_Root(d->window->roots[rootIndex]); | 449 | setCurrent_Root(d->window->base.roots[rootIndex]); |
450 | if (isFirstTab[rootIndex]) { | 450 | if (isFirstTab[rootIndex]) { |
451 | isFirstTab[rootIndex] = iFalse; | 451 | isFirstTab[rootIndex] = iFalse; |
452 | /* There is one pre-created tab in each root. */ | 452 | /* There is one pre-created tab in each root. */ |
@@ -469,7 +469,7 @@ static iBool loadState_App_(iApp *d) { | |||
469 | } | 469 | } |
470 | if (d->window->splitMode) { | 470 | if (d->window->splitMode) { |
471 | /* Update root placement. */ | 471 | /* Update root placement. */ |
472 | resize_Window(d->window, -1, -1); | 472 | resize_MainWindow(d->window, -1, -1); |
473 | } | 473 | } |
474 | iForIndices(i, current) { | 474 | iForIndices(i, current) { |
475 | postCommandf_Root(NULL, "tabs.switch page:%p", current[i]); | 475 | postCommandf_Root(NULL, "tabs.switch page:%p", current[i]); |
@@ -483,7 +483,7 @@ static iBool loadState_App_(iApp *d) { | |||
483 | static void saveState_App_(const iApp *d) { | 483 | static void saveState_App_(const iApp *d) { |
484 | iUnused(d); | 484 | iUnused(d); |
485 | trimCache_App(); | 485 | trimCache_App(); |
486 | iWindow *win = d->window; | 486 | iMainWindow *win = d->window; |
487 | /* UI state is saved in binary because it is quite complex (e.g., | 487 | /* UI state is saved in binary because it is quite complex (e.g., |
488 | navigation history, cached content) and depends closely on the widget | 488 | navigation history, cached content) and depends closely on the widget |
489 | tree. The data is largely not reorderable and should not be modified | 489 | tree. The data is largely not reorderable and should not be modified |
@@ -495,11 +495,11 @@ static void saveState_App_(const iApp *d) { | |||
495 | /* Begin with window state. */ { | 495 | /* Begin with window state. */ { |
496 | writeData_File(f, magicWindow_App_, 4); | 496 | writeData_File(f, magicWindow_App_, 4); |
497 | writeU32_File(f, win->splitMode); | 497 | writeU32_File(f, win->splitMode); |
498 | writeU32_File(f, win->keyRoot == win->roots[0] ? 0 : 1); | 498 | writeU32_File(f, win->base.keyRoot == win->base.roots[0] ? 0 : 1); |
499 | } | 499 | } |
500 | /* State of UI elements. */ { | 500 | /* State of UI elements. */ { |
501 | iForIndices(i, win->roots) { | 501 | iForIndices(i, win->base.roots) { |
502 | const iRoot *root = win->roots[i]; | 502 | const iRoot *root = win->base.roots[i]; |
503 | if (root) { | 503 | if (root) { |
504 | writeData_File(f, magicSidebar_App_, 4); | 504 | writeData_File(f, magicSidebar_App_, 4); |
505 | const iSidebarWidget *sidebar = findChild_Widget(root->widget, "sidebar"); | 505 | const iSidebarWidget *sidebar = findChild_Widget(root->widget, "sidebar"); |
@@ -520,7 +520,7 @@ static void saveState_App_(const iApp *d) { | |||
520 | const iWidget *widget = constAs_Widget(i.object); | 520 | const iWidget *widget = constAs_Widget(i.object); |
521 | writeData_File(f, magicTabDocument_App_, 4); | 521 | writeData_File(f, magicTabDocument_App_, 4); |
522 | int8_t flags = (document_Root(widget->root) == i.object ? current_DocumentStateFlag : 0); | 522 | int8_t flags = (document_Root(widget->root) == i.object ? current_DocumentStateFlag : 0); |
523 | if (widget->root == win->roots[1]) { | 523 | if (widget->root == win->base.roots[1]) { |
524 | flags |= rootIndex1_DocumentStateFlag; | 524 | flags |= rootIndex1_DocumentStateFlag; |
525 | } | 525 | } |
526 | write8_File(f, flags); | 526 | write8_File(f, flags); |
@@ -801,7 +801,7 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
801 | d->initialWindowRect.size.y = toInt_String(value_CommandLineArg(arg, 0)); | 801 | d->initialWindowRect.size.y = toInt_String(value_CommandLineArg(arg, 0)); |
802 | } | 802 | } |
803 | } | 803 | } |
804 | d->window = new_Window(d->initialWindowRect); | 804 | d->window = new_MainWindow(d->initialWindowRect); |
805 | load_Visited(d->visited, dataDir_App_()); | 805 | load_Visited(d->visited, dataDir_App_()); |
806 | load_Bookmarks(d->bookmarks, dataDir_App_()); | 806 | load_Bookmarks(d->bookmarks, dataDir_App_()); |
807 | load_MimeHooks(d->mimehooks, dataDir_App_()); | 807 | load_MimeHooks(d->mimehooks, dataDir_App_()); |
@@ -848,7 +848,7 @@ static void init_App_(iApp *d, int argc, char **argv) { | |||
848 | fetchRemote_Bookmarks(d->bookmarks); | 848 | fetchRemote_Bookmarks(d->bookmarks); |
849 | if (deviceType_App() != desktop_AppDeviceType) { | 849 | if (deviceType_App() != desktop_AppDeviceType) { |
850 | /* HACK: Force a resize so widgets update their state. */ | 850 | /* HACK: Force a resize so widgets update their state. */ |
851 | resize_Window(d->window, -1, -1); | 851 | resize_MainWindow(d->window, -1, -1); |
852 | } | 852 | } |
853 | } | 853 | } |
854 | 854 | ||
@@ -871,7 +871,7 @@ static void deinit_App(iApp *d) { | |||
871 | delete_GmCerts(d->certs); | 871 | delete_GmCerts(d->certs); |
872 | save_MimeHooks(d->mimehooks); | 872 | save_MimeHooks(d->mimehooks); |
873 | delete_MimeHooks(d->mimehooks); | 873 | delete_MimeHooks(d->mimehooks); |
874 | delete_Window(d->window); | 874 | delete_MainWindow(d->window); |
875 | d->window = NULL; | 875 | d->window = NULL; |
876 | deinit_CommandLine(&d->args); | 876 | deinit_CommandLine(&d->args); |
877 | iRelease(d->launchCommands); | 877 | iRelease(d->launchCommands); |
@@ -1110,7 +1110,7 @@ void processEvents_App(enum iAppEventMode eventMode) { | |||
1110 | clearCache_App_(); | 1110 | clearCache_App_(); |
1111 | break; | 1111 | break; |
1112 | case SDL_APP_WILLENTERFOREGROUND: | 1112 | case SDL_APP_WILLENTERFOREGROUND: |
1113 | invalidate_Window(d->window); | 1113 | invalidate_Window(as_Window(d->window)); |
1114 | break; | 1114 | break; |
1115 | case SDL_APP_DIDENTERFOREGROUND: | 1115 | case SDL_APP_DIDENTERFOREGROUND: |
1116 | gotEvents = iTrue; | 1116 | gotEvents = iTrue; |
@@ -1125,17 +1125,17 @@ void processEvents_App(enum iAppEventMode eventMode) { | |||
1125 | #if defined (iPlatformAppleMobile) | 1125 | #if defined (iPlatformAppleMobile) |
1126 | updateNowPlayingInfo_iOS(); | 1126 | updateNowPlayingInfo_iOS(); |
1127 | #endif | 1127 | #endif |
1128 | setFreezeDraw_Window(d->window, iTrue); | 1128 | setFreezeDraw_Window(as_Window(d), iTrue); |
1129 | savePrefs_App_(d); | 1129 | savePrefs_App_(d); |
1130 | saveState_App_(d); | 1130 | saveState_App_(d); |
1131 | break; | 1131 | break; |
1132 | case SDL_APP_TERMINATING: | 1132 | case SDL_APP_TERMINATING: |
1133 | setFreezeDraw_Window(d->window, iTrue); | 1133 | setFreezeDraw_Window(as_Window(d), iTrue); |
1134 | savePrefs_App_(d); | 1134 | savePrefs_App_(d); |
1135 | saveState_App_(d); | 1135 | saveState_App_(d); |
1136 | break; | 1136 | break; |
1137 | case SDL_DROPFILE: { | 1137 | case SDL_DROPFILE: { |
1138 | iBool wasUsed = processEvent_Window(d->window, &ev); | 1138 | iBool wasUsed = processEvent_MainWindow(d->window, &ev); |
1139 | if (!wasUsed) { | 1139 | if (!wasUsed) { |
1140 | iBool newTab = iFalse; | 1140 | iBool newTab = iFalse; |
1141 | if (elapsedSeconds_Time(&d->lastDropTime) < 0.1) { | 1141 | if (elapsedSeconds_Time(&d->lastDropTime) < 0.1) { |
@@ -1177,10 +1177,10 @@ void processEvents_App(enum iAppEventMode eventMode) { | |||
1177 | #endif | 1177 | #endif |
1178 | if (ev.type == SDL_USEREVENT && ev.user.code == arrange_UserEventCode) { | 1178 | if (ev.type == SDL_USEREVENT && ev.user.code == arrange_UserEventCode) { |
1179 | printf("[App] rearrange\n"); | 1179 | printf("[App] rearrange\n"); |
1180 | resize_Window(d->window, -1, -1); | 1180 | resize_MainWindow(d->window, -1, -1); |
1181 | iForIndices(i, d->window->roots) { | 1181 | iForIndices(i, d->window->base.roots) { |
1182 | if (d->window->roots[i]) { | 1182 | if (d->window->base.roots[i]) { |
1183 | d->window->roots[i]->pendingArrange = iFalse; | 1183 | d->window->base.roots[i]->pendingArrange = iFalse; |
1184 | } | 1184 | } |
1185 | } | 1185 | } |
1186 | // if (ev.user.data2 == d->window->roots[0]) { | 1186 | // if (ev.user.data2 == d->window->roots[0]) { |
@@ -1209,8 +1209,8 @@ void processEvents_App(enum iAppEventMode eventMode) { | |||
1209 | if (ev.wheel.which == 0) { | 1209 | if (ev.wheel.which == 0) { |
1210 | /* Trackpad with precise scrolling w/inertia (points). */ | 1210 | /* Trackpad with precise scrolling w/inertia (points). */ |
1211 | setPerPixel_MouseWheelEvent(&ev.wheel, iTrue); | 1211 | setPerPixel_MouseWheelEvent(&ev.wheel, iTrue); |
1212 | ev.wheel.x *= -d->window->pixelRatio; | 1212 | ev.wheel.x *= -d->window->base.pixelRatio; |
1213 | ev.wheel.y *= d->window->pixelRatio; | 1213 | ev.wheel.y *= d->window->base.pixelRatio; |
1214 | /* Only scroll on one axis at a time. */ | 1214 | /* Only scroll on one axis at a time. */ |
1215 | if (iAbs(ev.wheel.x) > iAbs(ev.wheel.y)) { | 1215 | if (iAbs(ev.wheel.x) > iAbs(ev.wheel.y)) { |
1216 | ev.wheel.y = 0; | 1216 | ev.wheel.y = 0; |
@@ -1268,8 +1268,8 @@ void processEvents_App(enum iAppEventMode eventMode) { | |||
1268 | } | 1268 | } |
1269 | } | 1269 | } |
1270 | #endif | 1270 | #endif |
1271 | d->window->lastHover = d->window->hover; | 1271 | d->window->base.lastHover = d->window->base.hover; |
1272 | iBool wasUsed = processEvent_Window(d->window, &ev); | 1272 | iBool wasUsed = processEvent_MainWindow(d->window, &ev); |
1273 | if (!wasUsed) { | 1273 | if (!wasUsed) { |
1274 | /* There may be a key bindings for this. */ | 1274 | /* There may be a key bindings for this. */ |
1275 | wasUsed = processEvent_Keys(&ev); | 1275 | wasUsed = processEvent_Keys(&ev); |
@@ -1289,8 +1289,8 @@ void processEvents_App(enum iAppEventMode eventMode) { | |||
1289 | handleCommand_MacOS(command_UserEvent(&ev)); | 1289 | handleCommand_MacOS(command_UserEvent(&ev)); |
1290 | #endif | 1290 | #endif |
1291 | if (isMetricsChange_UserEvent(&ev)) { | 1291 | if (isMetricsChange_UserEvent(&ev)) { |
1292 | iForIndices(i, d->window->roots) { | 1292 | iForIndices(i, d->window->base.roots) { |
1293 | iRoot *root = d->window->roots[i]; | 1293 | iRoot *root = d->window->base.roots[i]; |
1294 | if (root) { | 1294 | if (root) { |
1295 | arrange_Widget(root->widget); | 1295 | arrange_Widget(root->widget); |
1296 | } | 1296 | } |
@@ -1304,9 +1304,9 @@ void processEvents_App(enum iAppEventMode eventMode) { | |||
1304 | free(ev.user.data1); | 1304 | free(ev.user.data1); |
1305 | } | 1305 | } |
1306 | /* Update when hover has changed. */ | 1306 | /* Update when hover has changed. */ |
1307 | if (d->window->lastHover != d->window->hover) { | 1307 | if (d->window->base.lastHover != d->window->base.hover) { |
1308 | refresh_Widget(d->window->lastHover); | 1308 | refresh_Widget(d->window->base.lastHover); |
1309 | refresh_Widget(d->window->hover); | 1309 | refresh_Widget(d->window->base.hover); |
1310 | } | 1310 | } |
1311 | break; | 1311 | break; |
1312 | } | 1312 | } |
@@ -1362,15 +1362,16 @@ static int resizeWatcher_(void *user, SDL_Event *event) { | |||
1362 | dispatchEvent_Window(d->window, &u); | 1362 | dispatchEvent_Window(d->window, &u); |
1363 | } | 1363 | } |
1364 | #endif | 1364 | #endif |
1365 | drawWhileResizing_Window(d->window, winev->data1, winev->data2); | 1365 | drawWhileResizing_MainWindow(d->window, winev->data1, winev->data2); |
1366 | } | 1366 | } |
1367 | return 0; | 1367 | return 0; |
1368 | } | 1368 | } |
1369 | 1369 | ||
1370 | static int run_App_(iApp *d) { | 1370 | static int run_App_(iApp *d) { |
1371 | iForIndices(i, d->window->roots) { | 1371 | /* Initial arrangement. */ |
1372 | if (d->window->roots[i]) { | 1372 | iForIndices(i, d->window->base.roots) { |
1373 | arrange_Widget(d->window->roots[i]->widget); | 1373 | if (d->window->base.roots[i]) { |
1374 | arrange_Widget(d->window->base.roots[i]->widget); | ||
1374 | } | 1375 | } |
1375 | } | 1376 | } |
1376 | d->isRunning = iTrue; | 1377 | d->isRunning = iTrue; |
@@ -1384,7 +1385,7 @@ static int run_App_(iApp *d) { | |||
1384 | runTickers_App_(d); | 1385 | runTickers_App_(d); |
1385 | refresh_App(); | 1386 | refresh_App(); |
1386 | /* Change the widget tree while we are not iterating through it. */ | 1387 | /* Change the widget tree while we are not iterating through it. */ |
1387 | checkPendingSplit_Window(d->window); | 1388 | checkPendingSplit_MainWindow(d->window); |
1388 | recycle_Garbage(); | 1389 | recycle_Garbage(); |
1389 | } | 1390 | } |
1390 | SDL_DelEventWatch(resizeWatcher_, d); | 1391 | SDL_DelEventWatch(resizeWatcher_, d); |
@@ -1393,8 +1394,8 @@ static int run_App_(iApp *d) { | |||
1393 | 1394 | ||
1394 | void refresh_App(void) { | 1395 | void refresh_App(void) { |
1395 | iApp *d = &app_; | 1396 | iApp *d = &app_; |
1396 | iForIndices(i, d->window->roots) { | 1397 | iForIndices(i, d->window->base.roots) { |
1397 | iRoot *root = d->window->roots[i]; | 1398 | iRoot *root = d->window->base.roots[i]; |
1398 | if (root) { | 1399 | if (root) { |
1399 | destroyPending_Root(root); | 1400 | destroyPending_Root(root); |
1400 | } | 1401 | } |
@@ -1409,7 +1410,7 @@ void refresh_App(void) { | |||
1409 | } | 1410 | } |
1410 | // iTime draw; | 1411 | // iTime draw; |
1411 | // initCurrent_Time(&draw); | 1412 | // initCurrent_Time(&draw); |
1412 | draw_Window(d->window); | 1413 | draw_MainWindow(d->window); |
1413 | // printf("draw: %lld \u03bcs\n", (long long) (elapsedSeconds_Time(&draw) * 1000000)); | 1414 | // printf("draw: %lld \u03bcs\n", (long long) (elapsedSeconds_Time(&draw) * 1000000)); |
1414 | // fflush(stdout); | 1415 | // fflush(stdout); |
1415 | if (d->warmupFrames > 0) { | 1416 | if (d->warmupFrames > 0) { |
@@ -1545,7 +1546,7 @@ void postCommandf_App(const char *command, ...) { | |||
1545 | } | 1546 | } |
1546 | 1547 | ||
1547 | void rootOrder_App(iRoot *roots[2]) { | 1548 | void rootOrder_App(iRoot *roots[2]) { |
1548 | const iWindow *win = app_.window; | 1549 | const iWindow *win = as_Window(app_.window); |
1549 | roots[0] = win->keyRoot; | 1550 | roots[0] = win->keyRoot; |
1550 | roots[1] = (roots[0] == win->roots[0] ? win->roots[1] : win->roots[0]); | 1551 | roots[1] = (roots[0] == win->roots[0] ? win->roots[1] : win->roots[0]); |
1551 | } | 1552 | } |
@@ -1979,7 +1980,7 @@ const iString *searchQueryUrl_App(const iString *queryStringUnescaped) { | |||
1979 | 1980 | ||
1980 | iBool handleCommand_App(const char *cmd) { | 1981 | iBool handleCommand_App(const char *cmd) { |
1981 | iApp *d = &app_; | 1982 | iApp *d = &app_; |
1982 | const iBool isFrozen = !d->window || d->window->isDrawFrozen; | 1983 | const iBool isFrozen = !d->window || d->window->base.isDrawFrozen; |
1983 | if (equal_Command(cmd, "config.error")) { | 1984 | if (equal_Command(cmd, "config.error")) { |
1984 | makeSimpleMessage_Widget(uiTextCaution_ColorEscape "CONFIG ERROR", | 1985 | makeSimpleMessage_Widget(uiTextCaution_ColorEscape "CONFIG ERROR", |
1985 | format_CStr("Error in config file: %s\n" | 1986 | format_CStr("Error in config file: %s\n" |
@@ -2011,13 +2012,13 @@ iBool handleCommand_App(const char *cmd) { | |||
2011 | } | 2012 | } |
2012 | else if (equal_Command(cmd, "ui.split")) { | 2013 | else if (equal_Command(cmd, "ui.split")) { |
2013 | if (argLabel_Command(cmd, "swap")) { | 2014 | if (argLabel_Command(cmd, "swap")) { |
2014 | swapRoots_Window(d->window); | 2015 | swapRoots_MainWindow(d->window); |
2015 | return iTrue; | 2016 | return iTrue; |
2016 | } | 2017 | } |
2017 | d->window->pendingSplitMode = | 2018 | d->window->pendingSplitMode = |
2018 | (argLabel_Command(cmd, "axis") ? vertical_WindowSplit : 0) | (arg_Command(cmd) << 1); | 2019 | (argLabel_Command(cmd, "axis") ? vertical_WindowSplit : 0) | (arg_Command(cmd) << 1); |
2019 | const char *url = suffixPtr_Command(cmd, "url"); | 2020 | const char *url = suffixPtr_Command(cmd, "url"); |
2020 | setCStr_String(get_Window()->pendingSplitUrl, url ? url : ""); | 2021 | setCStr_String(d->window->pendingSplitUrl, url ? url : ""); |
2021 | postRefresh_App(); | 2022 | postRefresh_App(); |
2022 | return iTrue; | 2023 | return iTrue; |
2023 | } | 2024 | } |
@@ -2031,17 +2032,17 @@ iBool handleCommand_App(const char *cmd) { | |||
2031 | } | 2032 | } |
2032 | else if (equal_Command(cmd, "window.maximize")) { | 2033 | else if (equal_Command(cmd, "window.maximize")) { |
2033 | if (!argLabel_Command(cmd, "toggle")) { | 2034 | if (!argLabel_Command(cmd, "toggle")) { |
2034 | setSnap_Window(d->window, maximized_WindowSnap); | 2035 | setSnap_MainWindow(d->window, maximized_WindowSnap); |
2035 | } | 2036 | } |
2036 | else { | 2037 | else { |
2037 | setSnap_Window(d->window, snap_Window(d->window) == maximized_WindowSnap ? 0 : | 2038 | setSnap_MainWindow(d->window, snap_MainWindow(d->window) == maximized_WindowSnap ? 0 : |
2038 | maximized_WindowSnap); | 2039 | maximized_WindowSnap); |
2039 | } | 2040 | } |
2040 | return iTrue; | 2041 | return iTrue; |
2041 | } | 2042 | } |
2042 | else if (equal_Command(cmd, "window.fullscreen")) { | 2043 | else if (equal_Command(cmd, "window.fullscreen")) { |
2043 | const iBool wasFull = snap_Window(d->window) == fullscreen_WindowSnap; | 2044 | const iBool wasFull = snap_MainWindow(d->window) == fullscreen_WindowSnap; |
2044 | setSnap_Window(d->window, wasFull ? 0 : fullscreen_WindowSnap); | 2045 | setSnap_MainWindow(d->window, wasFull ? 0 : fullscreen_WindowSnap); |
2045 | postCommandf_App("window.fullscreen.changed arg:%d", !wasFull); | 2046 | postCommandf_App("window.fullscreen.changed arg:%d", !wasFull); |
2046 | return iTrue; | 2047 | return iTrue; |
2047 | } | 2048 | } |
@@ -2210,7 +2211,7 @@ iBool handleCommand_App(const char *cmd) { | |||
2210 | equal_Command(cmd, "prefs.mono.gopher.changed")) { | 2211 | equal_Command(cmd, "prefs.mono.gopher.changed")) { |
2211 | const iBool isSet = (arg_Command(cmd) != 0); | 2212 | const iBool isSet = (arg_Command(cmd) != 0); |
2212 | if (!isFrozen) { | 2213 | if (!isFrozen) { |
2213 | setFreezeDraw_Window(d->window, iTrue); | 2214 | setFreezeDraw_Window(as_Window(d->window), iTrue); |
2214 | } | 2215 | } |
2215 | if (startsWith_CStr(cmd, "prefs.mono.gemini")) { | 2216 | if (startsWith_CStr(cmd, "prefs.mono.gemini")) { |
2216 | d->prefs.monospaceGemini = isSet; | 2217 | d->prefs.monospaceGemini = isSet; |
@@ -2405,8 +2406,8 @@ iBool handleCommand_App(const char *cmd) { | |||
2405 | iRoot *root = get_Root(); | 2406 | iRoot *root = get_Root(); |
2406 | iRoot *oldRoot = root; | 2407 | iRoot *oldRoot = root; |
2407 | if (newTab & otherRoot_OpenTabFlag) { | 2408 | if (newTab & otherRoot_OpenTabFlag) { |
2408 | root = otherRoot_Window(d->window, root); | 2409 | root = otherRoot_Window(as_Window(d->window), root); |
2409 | setKeyRoot_Window(d->window, root); | 2410 | setKeyRoot_Window(as_Window(d->window), root); |
2410 | setCurrent_Root(root); /* need to change for widget creation */ | 2411 | setCurrent_Root(root); /* need to change for widget creation */ |
2411 | } | 2412 | } |
2412 | iDocumentWidget *doc = document_Command(cmd); | 2413 | iDocumentWidget *doc = document_Command(cmd); |
@@ -2560,7 +2561,8 @@ iBool handleCommand_App(const char *cmd) { | |||
2560 | return iTrue; | 2561 | return iTrue; |
2561 | } | 2562 | } |
2562 | else if (equal_Command(cmd, "keyroot.next")) { | 2563 | else if (equal_Command(cmd, "keyroot.next")) { |
2563 | if (setKeyRoot_Window(d->window, otherRoot_Window(d->window, d->window->keyRoot))) { | 2564 | if (setKeyRoot_Window(as_Window(d->window), |
2565 | otherRoot_Window(as_Window(d->window), d->window->base.keyRoot))) { | ||
2564 | setFocus_Widget(NULL); | 2566 | setFocus_Widget(NULL); |
2565 | } | 2567 | } |
2566 | return iTrue; | 2568 | return iTrue; |
@@ -2592,7 +2594,7 @@ iBool handleCommand_App(const char *cmd) { | |||
2592 | format_CStr("returnkey.set arg:%d", d->prefs.returnKey)); | 2594 | format_CStr("returnkey.set arg:%d", d->prefs.returnKey)); |
2593 | setToggle_Widget(findChild_Widget(dlg, "prefs.retainwindow"), d->prefs.retainWindowSize); | 2595 | setToggle_Widget(findChild_Widget(dlg, "prefs.retainwindow"), d->prefs.retainWindowSize); |
2594 | setText_InputWidget(findChild_Widget(dlg, "prefs.uiscale"), | 2596 | setText_InputWidget(findChild_Widget(dlg, "prefs.uiscale"), |
2595 | collectNewFormat_String("%g", uiScale_Window(d->window))); | 2597 | collectNewFormat_String("%g", uiScale_Window(as_Window(d->window)))); |
2596 | setFlags_Widget(findChild_Widget(dlg, format_CStr("prefs.font.%d", d->prefs.font)), | 2598 | setFlags_Widget(findChild_Widget(dlg, format_CStr("prefs.font.%d", d->prefs.font)), |
2597 | selected_WidgetFlag, | 2599 | selected_WidgetFlag, |
2598 | iTrue); | 2600 | iTrue); |
@@ -2749,7 +2751,7 @@ iBool handleCommand_App(const char *cmd) { | |||
2749 | /* Set of open tabs has changed. */ | 2751 | /* Set of open tabs has changed. */ |
2750 | postCommand_App("document.openurls.changed"); | 2752 | postCommand_App("document.openurls.changed"); |
2751 | if (deviceType_App() == phone_AppDeviceType) { | 2753 | if (deviceType_App() == phone_AppDeviceType) { |
2752 | showToolbar_Root(d->window->roots[0], iTrue); | 2754 | showToolbar_Root(d->window->base.roots[0], iTrue); |
2753 | } | 2755 | } |
2754 | return iFalse; | 2756 | return iFalse; |
2755 | } | 2757 | } |
@@ -2825,8 +2827,8 @@ iBool handleCommand_App(const char *cmd) { | |||
2825 | } | 2827 | } |
2826 | else if (equal_Command(cmd, "ipc.signal")) { | 2828 | else if (equal_Command(cmd, "ipc.signal")) { |
2827 | if (argLabel_Command(cmd, "raise")) { | 2829 | if (argLabel_Command(cmd, "raise")) { |
2828 | if (d->window && d->window->win) { | 2830 | if (d->window && d->window->base.win) { |
2829 | SDL_RaiseWindow(d->window->win); | 2831 | SDL_RaiseWindow(d->window->base.win); |
2830 | } | 2832 | } |
2831 | } | 2833 | } |
2832 | signal_Ipc(arg_Command(cmd)); | 2834 | signal_Ipc(arg_Command(cmd)); |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 8ea695d5..ed9e41d6 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -934,7 +934,7 @@ static void updateWindowTitle_DocumentWidget_(const iDocumentWidget *d) { | |||
934 | iString *text = collect_String(joinCStr_StringArray(title, " \u2014 ")); | 934 | iString *text = collect_String(joinCStr_StringArray(title, " \u2014 ")); |
935 | if (setWindow) { | 935 | if (setWindow) { |
936 | /* Longest version for the window title, and omit the icon. */ | 936 | /* Longest version for the window title, and omit the icon. */ |
937 | setTitle_Window(get_Window(), text); | 937 | setTitle_MainWindow(get_MainWindow(), text); |
938 | setWindow = iFalse; | 938 | setWindow = iFalse; |
939 | } | 939 | } |
940 | const iChar siteIcon = siteIcon_GmDocument(d->doc); | 940 | const iChar siteIcon = siteIcon_GmDocument(d->doc); |
diff --git a/src/ui/paint.c b/src/ui/paint.c index a3ee32c6..5506f845 100644 --- a/src/ui/paint.c +++ b/src/ui/paint.c | |||
@@ -152,6 +152,9 @@ void drawSoftShadow_Paint(const iPaint *d, iRect inner, int thickness, int color | |||
152 | addv_I2(&inner.pos, origin_Paint); | 152 | addv_I2(&inner.pos, origin_Paint); |
153 | SDL_Renderer *render = renderer_Paint_(d); | 153 | SDL_Renderer *render = renderer_Paint_(d); |
154 | SDL_Texture *shadow = get_Window()->borderShadow; | 154 | SDL_Texture *shadow = get_Window()->borderShadow; |
155 | if (!shadow) { | ||
156 | return; | ||
157 | } | ||
155 | const iInt2 size = size_SDLTexture(shadow); | 158 | const iInt2 size = size_SDLTexture(shadow); |
156 | const iRect outer = expanded_Rect(inner, init1_I2(thickness)); | 159 | const iRect outer = expanded_Rect(inner, init1_I2(thickness)); |
157 | const iColor clr = get_Color(color); | 160 | const iColor clr = get_Color(color); |
diff --git a/src/ui/root.c b/src/ui/root.c index 6ea5f521..52a08eca 100644 --- a/src/ui/root.c +++ b/src/ui/root.c | |||
@@ -383,18 +383,18 @@ static iBool handleRootCommands_(iWidget *root, const char *cmd) { | |||
383 | else if (equal_Command(cmd, "window.setrect")) { | 383 | else if (equal_Command(cmd, "window.setrect")) { |
384 | const int snap = argLabel_Command(cmd, "snap"); | 384 | const int snap = argLabel_Command(cmd, "snap"); |
385 | if (snap) { | 385 | if (snap) { |
386 | iWindow *window = get_Window(); | 386 | iMainWindow *window = get_MainWindow(); |
387 | iInt2 coord = coord_Command(cmd); | 387 | iInt2 coord = coord_Command(cmd); |
388 | iInt2 size = init_I2(argLabel_Command(cmd, "width"), | 388 | iInt2 size = init_I2(argLabel_Command(cmd, "width"), |
389 | argLabel_Command(cmd, "height")); | 389 | argLabel_Command(cmd, "height")); |
390 | SDL_SetWindowPosition(window->win, coord.x, coord.y); | 390 | SDL_SetWindowPosition(window->base.win, coord.x, coord.y); |
391 | SDL_SetWindowSize(window->win, size.x, size.y); | 391 | SDL_SetWindowSize(window->base.win, size.x, size.y); |
392 | window->place.snap = snap; | 392 | window->place.snap = snap; |
393 | return iTrue; | 393 | return iTrue; |
394 | } | 394 | } |
395 | } | 395 | } |
396 | else if (equal_Command(cmd, "window.restore")) { | 396 | else if (equal_Command(cmd, "window.restore")) { |
397 | setSnap_Window(get_Window(), none_WindowSnap); | 397 | setSnap_MainWindow(get_MainWindow(), none_WindowSnap); |
398 | return iTrue; | 398 | return iTrue; |
399 | } | 399 | } |
400 | else if (equal_Command(cmd, "window.minimize")) { | 400 | else if (equal_Command(cmd, "window.minimize")) { |
@@ -1525,5 +1525,5 @@ iRect safeRect_Root(const iRoot *d) { | |||
1525 | } | 1525 | } |
1526 | 1526 | ||
1527 | iInt2 visibleSize_Root(const iRoot *d) { | 1527 | iInt2 visibleSize_Root(const iRoot *d) { |
1528 | return addY_I2(size_Root(d), -get_Window()->keyboardHeight); | 1528 | return addY_I2(size_Root(d), -get_MainWindow()->keyboardHeight); |
1529 | } | 1529 | } |
diff --git a/src/ui/uploadwidget.c b/src/ui/uploadwidget.c index 72608851..ba7545fd 100644 --- a/src/ui/uploadwidget.c +++ b/src/ui/uploadwidget.c | |||
@@ -97,7 +97,7 @@ static void updateInputMaxHeight_UploadWidget_(iUploadWidget *d) { | |||
97 | height_Widget(findChild_Widget(w, "dialogbuttons")) + | 97 | height_Widget(findChild_Widget(w, "dialogbuttons")) + |
98 | 12 * gap_UI); | 98 | 12 * gap_UI); |
99 | const int avail = bottom_Rect(safeRect_Root(w->root)) - footerHeight - | 99 | const int avail = bottom_Rect(safeRect_Root(w->root)) - footerHeight - |
100 | get_Window()->keyboardHeight; | 100 | get_MainWindow()->keyboardHeight; |
101 | setLineLimits_InputWidget(d->input, | 101 | setLineLimits_InputWidget(d->input, |
102 | minLines_InputWidget(d->input), | 102 | minLines_InputWidget(d->input), |
103 | iMaxi(minLines_InputWidget(d->input), | 103 | iMaxi(minLines_InputWidget(d->input), |
diff --git a/src/ui/util.c b/src/ui/util.c index 01939e66..721aed2d 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -1222,7 +1222,7 @@ static void updateValueInputWidth_(iWidget *dlg) { | |||
1222 | iMin(rootSize.x, iMaxi(iMaxi(100 * gap_UI, title->rect.size.x), prompt->rect.size.x)); | 1222 | iMin(rootSize.x, iMaxi(iMaxi(100 * gap_UI, title->rect.size.x), prompt->rect.size.x)); |
1223 | } | 1223 | } |
1224 | /* Adjust the maximum number of visible lines. */ | 1224 | /* Adjust the maximum number of visible lines. */ |
1225 | int footer = 6 * gap_UI + get_Window()->keyboardHeight; | 1225 | int footer = 6 * gap_UI + get_MainWindow()->keyboardHeight; |
1226 | iWidget *buttons = findChild_Widget(dlg, "dialogbuttons"); | 1226 | iWidget *buttons = findChild_Widget(dlg, "dialogbuttons"); |
1227 | if (buttons) { | 1227 | if (buttons) { |
1228 | footer += height_Widget(buttons); | 1228 | footer += height_Widget(buttons); |
diff --git a/src/ui/widget.c b/src/ui/widget.c index c1fb9e95..23c19315 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c | |||
@@ -1088,7 +1088,7 @@ void scrollInfo_Widget(const iWidget *d, iWidgetScrollInfo *info) { | |||
1088 | iRect bounds = boundsWithoutVisualOffset_Widget(d); | 1088 | iRect bounds = boundsWithoutVisualOffset_Widget(d); |
1089 | const iRect winRect = adjusted_Rect(safeRect_Root(d->root), | 1089 | const iRect winRect = adjusted_Rect(safeRect_Root(d->root), |
1090 | zero_I2(), | 1090 | zero_I2(), |
1091 | init_I2(0, -get_Window()->keyboardHeight)); | 1091 | init_I2(0, -get_MainWindow()->keyboardHeight)); |
1092 | info->height = bounds.size.y; | 1092 | info->height = bounds.size.y; |
1093 | info->avail = height_Rect(winRect); | 1093 | info->avail = height_Rect(winRect); |
1094 | if (info->avail >= info->height) { | 1094 | if (info->avail >= info->height) { |
@@ -1109,7 +1109,7 @@ iBool scrollOverflow_Widget(iWidget *d, int delta) { | |||
1109 | iRect bounds = boundsWithoutVisualOffset_Widget(d); | 1109 | iRect bounds = boundsWithoutVisualOffset_Widget(d); |
1110 | const iRect winRect = adjusted_Rect(safeRect_Root(d->root), | 1110 | const iRect winRect = adjusted_Rect(safeRect_Root(d->root), |
1111 | zero_I2(), | 1111 | zero_I2(), |
1112 | init_I2(0, -get_Window()->keyboardHeight)); | 1112 | init_I2(0, -get_MainWindow()->keyboardHeight)); |
1113 | const int yTop = top_Rect(winRect); | 1113 | const int yTop = top_Rect(winRect); |
1114 | const int yBottom = bottom_Rect(winRect); | 1114 | const int yBottom = bottom_Rect(winRect); |
1115 | if (top_Rect(bounds) >= yTop && bottom_Rect(bounds) < yBottom) { | 1115 | if (top_Rect(bounds) >= yTop && bottom_Rect(bounds) < yBottom) { |
diff --git a/src/ui/window.c b/src/ui/window.c index b8198636..92125d81 100644 --- a/src/ui/window.c +++ b/src/ui/window.c | |||
@@ -67,7 +67,7 @@ static float initialUiScale_ = 1.1f; | |||
67 | 67 | ||
68 | static iBool isOpenGLRenderer_; | 68 | static iBool isOpenGLRenderer_; |
69 | 69 | ||
70 | iDefineTypeConstructionArgs(Window, (iRect rect), rect) | 70 | iDefineTypeConstructionArgs(MainWindow, (iRect rect), rect) |
71 | 71 | ||
72 | /* TODO: Define menus per platform. */ | 72 | /* TODO: Define menus per platform. */ |
73 | 73 | ||
@@ -169,17 +169,17 @@ int numRoots_Window(const iWindow *d) { | |||
169 | return num; | 169 | return num; |
170 | } | 170 | } |
171 | 171 | ||
172 | static void windowSizeChanged_Window_(iWindow *d) { | 172 | static void windowSizeChanged_MainWindow_(iMainWindow *d) { |
173 | const int numRoots = numRoots_Window(d); | 173 | const int numRoots = numRoots_Window(as_Window(d)); |
174 | const iInt2 rootSize = d->size; | 174 | const iInt2 rootSize = d->base.size; |
175 | const int weights[2] = { | 175 | const int weights[2] = { |
176 | d->roots[0] ? (d->splitMode & twoToOne_WindowSplit ? 2 : 1) : 0, | 176 | d->base.roots[0] ? (d->splitMode & twoToOne_WindowSplit ? 2 : 1) : 0, |
177 | d->roots[1] ? (d->splitMode & oneToTwo_WindowSplit ? 2 : 1) : 0, | 177 | d->base.roots[1] ? (d->splitMode & oneToTwo_WindowSplit ? 2 : 1) : 0, |
178 | }; | 178 | }; |
179 | const int totalWeight = weights[0] + weights[1]; | 179 | const int totalWeight = weights[0] + weights[1]; |
180 | int w = 0; | 180 | int w = 0; |
181 | iForIndices(i, d->roots) { | 181 | iForIndices(i, d->base.roots) { |
182 | iRoot *root = d->roots[i]; | 182 | iRoot *root = d->base.roots[i]; |
183 | if (root) { | 183 | if (root) { |
184 | iRect *rect = &root->widget->rect; | 184 | iRect *rect = &root->widget->rect; |
185 | /* Horizontal split frame. */ | 185 | /* Horizontal split frame. */ |
@@ -199,26 +199,26 @@ static void windowSizeChanged_Window_(iWindow *d) { | |||
199 | } | 199 | } |
200 | } | 200 | } |
201 | 201 | ||
202 | static void setupUserInterface_Window(iWindow *d) { | 202 | static void setupUserInterface_MainWindow(iMainWindow *d) { |
203 | #if defined (iHaveNativeMenus) | 203 | #if defined (iHaveNativeMenus) |
204 | insertMacMenus_(); | 204 | insertMacMenus_(); |
205 | #endif | 205 | #endif |
206 | /* One root is created by default. */ | 206 | /* One root is created by default. */ |
207 | d->roots[0] = new_Root(); | 207 | d->base.roots[0] = new_Root(); |
208 | setCurrent_Root(d->roots[0]); | 208 | setCurrent_Root(d->base.roots[0]); |
209 | createUserInterface_Root(d->roots[0]); | 209 | createUserInterface_Root(d->base.roots[0]); |
210 | setCurrent_Root(NULL); | 210 | setCurrent_Root(NULL); |
211 | /* One of the roots always has keyboard input focus. */ | 211 | /* One of the roots always has keyboard input focus. */ |
212 | d->keyRoot = d->roots[0]; | 212 | d->base.keyRoot = d->base.roots[0]; |
213 | } | 213 | } |
214 | 214 | ||
215 | static void updateSize_Window_(iWindow *d, iBool notifyAlways) { | 215 | static void updateSize_MainWindow_(iMainWindow *d, iBool notifyAlways) { |
216 | iInt2 *size = &d->size; | 216 | iInt2 *size = &d->base.size; |
217 | const iInt2 oldSize = *size; | 217 | const iInt2 oldSize = *size; |
218 | SDL_GetRendererOutputSize(d->render, &size->x, &size->y); | 218 | SDL_GetRendererOutputSize(d->base.render, &size->x, &size->y); |
219 | size->y -= d->keyboardHeight; | 219 | size->y -= d->keyboardHeight; |
220 | if (notifyAlways || !isEqual_I2(oldSize, *size)) { | 220 | if (notifyAlways || !isEqual_I2(oldSize, *size)) { |
221 | windowSizeChanged_Window_(d); | 221 | windowSizeChanged_MainWindow_(d); |
222 | if (!isEqual_I2(*size, d->place.lastNotifiedSize)) { | 222 | if (!isEqual_I2(*size, d->place.lastNotifiedSize)) { |
223 | const iBool isHoriz = (d->place.lastNotifiedSize.x != size->x); | 223 | const iBool isHoriz = (d->place.lastNotifiedSize.x != size->x); |
224 | const iBool isVert = (d->place.lastNotifiedSize.y != size->y); | 224 | const iBool isVert = (d->place.lastNotifiedSize.y != size->y); |
@@ -234,8 +234,8 @@ static void updateSize_Window_(iWindow *d, iBool notifyAlways) { | |||
234 | } | 234 | } |
235 | } | 235 | } |
236 | 236 | ||
237 | void drawWhileResizing_Window(iWindow *d, int w, int h) { | 237 | void drawWhileResizing_MainWindow(iMainWindow *d, int w, int h) { |
238 | draw_Window(d); | 238 | draw_MainWindow(d); |
239 | } | 239 | } |
240 | 240 | ||
241 | static float pixelRatio_Window_(const iWindow *d) { | 241 | static float pixelRatio_Window_(const iWindow *d) { |
@@ -308,7 +308,7 @@ static iRoot *rootAt_Window_(const iWindow *d, iInt2 coord) { | |||
308 | } | 308 | } |
309 | 309 | ||
310 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) | 310 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) |
311 | static SDL_HitTestResult hitTest_Window_(SDL_Window *win, const SDL_Point *pos, void *data) { | 311 | static SDL_HitTestResult hitTest_MainWindow_(SDL_Window *win, const SDL_Point *pos, void *data) { |
312 | iWindow *d = data; | 312 | iWindow *d = data; |
313 | iAssert(d->win == win); | 313 | iAssert(d->win == win); |
314 | if (SDL_GetWindowFlags(d->win) & (SDL_WINDOW_MOUSE_CAPTURE | SDL_WINDOW_FULLSCREEN_DESKTOP)) { | 314 | if (SDL_GetWindowFlags(d->win) & (SDL_WINDOW_MOUSE_CAPTURE | SDL_WINDOW_FULLSCREEN_DESKTOP)) { |
@@ -361,19 +361,22 @@ SDL_HitTestResult hitTest_Window(const iWindow *d, iInt2 pos) { | |||
361 | #endif | 361 | #endif |
362 | 362 | ||
363 | iBool create_Window_(iWindow *d, iRect rect, uint32_t flags) { | 363 | iBool create_Window_(iWindow *d, iRect rect, uint32_t flags) { |
364 | flags |= SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN; | 364 | flags |= SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN; |
365 | if (d->type == main_WindowType) { | ||
366 | flags |= SDL_WINDOW_RESIZABLE; | ||
365 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) | 367 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) |
366 | if (prefs_App()->customFrame) { | 368 | if (prefs_App()->customFrame) { |
367 | /* We are drawing a custom frame so hide the default one. */ | 369 | /* We are drawing a custom frame so hide the default one. */ |
368 | flags |= SDL_WINDOW_BORDERLESS; | 370 | flags |= SDL_WINDOW_BORDERLESS; |
369 | } | 371 | } |
370 | #endif | 372 | #endif |
373 | } | ||
371 | if (SDL_CreateWindowAndRenderer( | 374 | if (SDL_CreateWindowAndRenderer( |
372 | width_Rect(rect), height_Rect(rect), flags, &d->win, &d->render)) { | 375 | width_Rect(rect), height_Rect(rect), flags, &d->win, &d->render)) { |
373 | return iFalse; | 376 | return iFalse; |
374 | } | 377 | } |
375 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) | 378 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) |
376 | if (prefs_App()->customFrame) { | 379 | if (type_Window(d) == main_WindowType && prefs_App()->customFrame) { |
377 | /* Register a handler for window hit testing (drag, resize). */ | 380 | /* Register a handler for window hit testing (drag, resize). */ |
378 | SDL_SetWindowHitTest(d->win, hitTest_Window_, d); | 381 | SDL_SetWindowHitTest(d->win, hitTest_Window_, d); |
379 | SDL_SetWindowResizable(d->win, SDL_TRUE); | 382 | SDL_SetWindowResizable(d->win, SDL_TRUE); |
@@ -397,40 +400,28 @@ static SDL_Surface *loadImage_(const iBlock *data, int resized) { | |||
397 | pixels, w, h, 8 * num, w * num, SDL_PIXELFORMAT_RGBA32); | 400 | pixels, w, h, 8 * num, w * num, SDL_PIXELFORMAT_RGBA32); |
398 | } | 401 | } |
399 | 402 | ||
400 | void init_Window(iWindow *d, iRect rect) { | 403 | void init_Window(iWindow *d, enum iWindowType type, iRect rect, uint32_t flags) { |
401 | theWindow_ = d; | 404 | d->type = type; |
402 | d->win = NULL; | 405 | d->win = NULL; |
403 | d->size = zero_I2(); /* will be updated below */ | 406 | d->size = zero_I2(); /* will be updated below */ |
404 | iZap(d->roots); | 407 | d->hover = NULL; |
405 | d->splitMode = d->pendingSplitMode = 0; | 408 | d->lastHover = NULL; |
406 | d->pendingSplitUrl = new_String(); | 409 | d->mouseGrab = NULL; |
407 | d->hover = NULL; | 410 | d->focus = NULL; |
408 | d->lastHover = NULL; | ||
409 | d->mouseGrab = NULL; | ||
410 | d->focus = NULL; | ||
411 | iZap(d->cursors); | ||
412 | d->place.initialPos = rect.pos; | ||
413 | d->place.normalRect = rect; | ||
414 | d->place.lastNotifiedSize = zero_I2(); | ||
415 | d->place.snap = 0; | ||
416 | d->pendingCursor = NULL; | 411 | d->pendingCursor = NULL; |
417 | d->isDrawFrozen = iTrue; | 412 | d->isDrawFrozen = iTrue; |
418 | d->isExposed = iFalse; | 413 | d->isExposed = iFalse; |
419 | d->isMinimized = iFalse; | 414 | d->isMinimized = iFalse; |
420 | d->isInvalidated = iFalse; /* set when posting event, to avoid repeated events */ | 415 | d->isInvalidated = iFalse; /* set when posting event, to avoid repeated events */ |
421 | d->isMouseInside = iTrue; | 416 | d->isMouseInside = iTrue; |
422 | d->ignoreClick = iFalse; | 417 | d->ignoreClick = iFalse; |
423 | d->focusGainedAt = 0; | 418 | d->focusGainedAt = 0; |
424 | d->keyboardHeight = 0; | 419 | d->presentTime = 0.0; |
425 | uint32_t flags = 0; | 420 | d->frameTime = SDL_GetTicks(); |
426 | #if defined (iPlatformAppleDesktop) | 421 | d->keyRoot = NULL; |
427 | SDL_SetHint(SDL_HINT_RENDER_DRIVER, shouldDefaultToMetalRenderer_MacOS() ? "metal" : "opengl"); | 422 | d->borderShadow = NULL; |
428 | #elif defined (iPlatformAppleMobile) | 423 | iZap(d->roots); |
429 | SDL_SetHint(SDL_HINT_RENDER_DRIVER, "metal"); | 424 | iZap(d->cursors); |
430 | #else | ||
431 | flags |= SDL_WINDOW_OPENGL; | ||
432 | #endif | ||
433 | SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1"); | ||
434 | /* First try SDL's default renderer that should be the best option. */ | 425 | /* First try SDL's default renderer that should be the best option. */ |
435 | if (forceSoftwareRender_App() || !create_Window_(d, rect, flags)) { | 426 | if (forceSoftwareRender_App() || !create_Window_(d, rect, flags)) { |
436 | /* No luck, maybe software only? This should always work as long as there is a display. */ | 427 | /* No luck, maybe software only? This should always work as long as there is a display. */ |
@@ -443,40 +434,74 @@ void init_Window(iWindow *d, iRect rect) { | |||
443 | if (left_Rect(rect) >= 0 || top_Rect(rect) >= 0) { | 434 | if (left_Rect(rect) >= 0 || top_Rect(rect) >= 0) { |
444 | SDL_SetWindowPosition(d->win, left_Rect(rect), top_Rect(rect)); | 435 | SDL_SetWindowPosition(d->win, left_Rect(rect), top_Rect(rect)); |
445 | } | 436 | } |
446 | #if defined (iPlatformMobile) | 437 | SDL_GetRendererOutputSize(d->render, &d->size.x, &d->size.y); |
438 | drawBlank_Window_(d); | ||
439 | d->pixelRatio = pixelRatio_Window_(d); /* point/pixel conversion */ | ||
440 | d->displayScale = displayScale_Window_(d); | ||
441 | d->uiScale = initialUiScale_; | ||
442 | /* TODO: Ratios, scales, and metrics must be window-specific, not global. */ | ||
443 | setScale_Metrics(d->pixelRatio * d->displayScale * d->uiScale); | ||
444 | } | ||
445 | |||
446 | void deinit_Window(iWindow *d) { | ||
447 | SDL_DestroyRenderer(d->render); | ||
448 | SDL_DestroyWindow(d->win); | ||
449 | iForIndices(i, d->cursors) { | ||
450 | if (d->cursors[i]) { | ||
451 | SDL_FreeCursor(d->cursors[i]); | ||
452 | } | ||
453 | } | ||
454 | } | ||
455 | |||
456 | void init_MainWindow(iMainWindow *d, iRect rect) { | ||
457 | theWindow_ = &d->base; | ||
458 | uint32_t flags = 0; | ||
459 | #if defined (iPlatformAppleDesktop) | ||
460 | SDL_SetHint(SDL_HINT_RENDER_DRIVER, shouldDefaultToMetalRenderer_MacOS() ? "metal" : "opengl"); | ||
461 | #elif defined (iPlatformAppleMobile) | ||
462 | SDL_SetHint(SDL_HINT_RENDER_DRIVER, "metal"); | ||
463 | #else | ||
464 | flags |= SDL_WINDOW_OPENGL; | ||
465 | #endif | ||
466 | SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1"); | ||
467 | init_Window(&d->base, main_WindowType, rect, flags); | ||
468 | d->splitMode = d->pendingSplitMode = 0; | ||
469 | d->pendingSplitUrl = new_String(); | ||
470 | d->place.initialPos = rect.pos; | ||
471 | d->place.normalRect = rect; | ||
472 | d->place.lastNotifiedSize = zero_I2(); | ||
473 | d->place.snap = 0; | ||
474 | d->keyboardHeight = 0; | ||
475 | #if defined(iPlatformMobile) | ||
447 | const iInt2 minSize = zero_I2(); /* windows aren't independently resizable */ | 476 | const iInt2 minSize = zero_I2(); /* windows aren't independently resizable */ |
448 | #else | 477 | #else |
449 | const iInt2 minSize = init_I2(425, 325); | 478 | const iInt2 minSize = init_I2(425, 325); |
450 | #endif | 479 | #endif |
451 | SDL_SetWindowMinimumSize(d->win, minSize.x, minSize.y); | 480 | SDL_SetWindowMinimumSize(d->base.win, minSize.x, minSize.y); |
452 | SDL_SetWindowTitle(d->win, "Lagrange"); | 481 | SDL_SetWindowTitle(d->base.win, "Lagrange"); |
453 | /* Some info. */ { | 482 | /* Some info. */ { |
454 | SDL_RendererInfo info; | 483 | SDL_RendererInfo info; |
455 | SDL_GetRendererInfo(d->render, &info); | 484 | SDL_GetRendererInfo(d->base.render, &info); |
456 | isOpenGLRenderer_ = !iCmpStr(info.name, "opengl"); | 485 | isOpenGLRenderer_ = !iCmpStr(info.name, "opengl"); |
457 | printf("[window] renderer: %s%s\n", info.name, | 486 | printf("[window] renderer: %s%s\n", |
487 | info.name, | ||
458 | info.flags & SDL_RENDERER_ACCELERATED ? " (accelerated)" : ""); | 488 | info.flags & SDL_RENDERER_ACCELERATED ? " (accelerated)" : ""); |
459 | #if !defined (NDEBUG) | 489 | #if !defined(NDEBUG) |
460 | printf("[window] max texture size: %d x %d\n", | 490 | printf("[window] max texture size: %d x %d\n", |
461 | info.max_texture_width, | 491 | info.max_texture_width, |
462 | info.max_texture_height); | 492 | info.max_texture_height); |
463 | for (size_t i = 0; i < info.num_texture_formats; ++i) { | 493 | for (size_t i = 0; i < info.num_texture_formats; ++i) { |
464 | printf("[window] supported texture format: %s\n", SDL_GetPixelFormatName( | 494 | printf("[window] supported texture format: %s\n", |
465 | info.texture_formats[i])); | 495 | SDL_GetPixelFormatName(info.texture_formats[i])); |
466 | } | 496 | } |
467 | #endif | 497 | #endif |
468 | } | 498 | } |
469 | drawBlank_Window_(d); | 499 | #if defined(iPlatformMsys) |
470 | d->pixelRatio = pixelRatio_Window_(d); /* point/pixel conversion */ | 500 | SDL_SetWindowMinimumSize(d->win, minSize.x * d->base.displayScale, minSize.y * d->base.displayScale); |
471 | d->displayScale = displayScale_Window_(d); | 501 | useExecutableIconResource_SDLWindow(d->base.win); |
472 | d->uiScale = initialUiScale_; | ||
473 | setScale_Metrics(d->pixelRatio * d->displayScale * d->uiScale); | ||
474 | #if defined (iPlatformMsys) | ||
475 | SDL_SetWindowMinimumSize(d->win, minSize.x * d->displayScale, minSize.y * d->displayScale); | ||
476 | useExecutableIconResource_SDLWindow(d->win); | ||
477 | #endif | 502 | #endif |
478 | #if defined (iPlatformLinux) | 503 | #if defined (iPlatformLinux) |
479 | SDL_SetWindowMinimumSize(d->win, minSize.x * d->pixelRatio, minSize.y * d->pixelRatio); | 504 | SDL_SetWindowMinimumSize(d->win, minSize.x * d->base.pixelRatio, minSize.y * d->base.pixelRatio); |
480 | /* Load the window icon. */ { | 505 | /* Load the window icon. */ { |
481 | SDL_Surface *surf = loadImage_(&imageLagrange64_Embedded, 0); | 506 | SDL_Surface *surf = loadImage_(&imageLagrange64_Embedded, 0); |
482 | SDL_SetWindowIcon(d->win, surf); | 507 | SDL_SetWindowIcon(d->win, surf); |
@@ -487,18 +512,14 @@ void init_Window(iWindow *d, iRect rect) { | |||
487 | #if defined (iPlatformAppleMobile) | 512 | #if defined (iPlatformAppleMobile) |
488 | setupWindow_iOS(d); | 513 | setupWindow_iOS(d); |
489 | #endif | 514 | #endif |
490 | d->presentTime = 0.0; | 515 | init_Text(d->base.render); |
491 | d->frameTime = SDL_GetTicks(); | 516 | SDL_GetRendererOutputSize(d->base.render, &d->base.size.x, &d->base.size.y); |
492 | d->loadAnimTimer = 0; | 517 | setupUserInterface_MainWindow(d); |
493 | init_Text(d->render); | ||
494 | SDL_GetRendererOutputSize(d->render, &d->size.x, &d->size.y); | ||
495 | setupUserInterface_Window(d); | ||
496 | postCommand_App("~bindings.changed"); /* update from bindings */ | 518 | postCommand_App("~bindings.changed"); /* update from bindings */ |
497 | //updateSize_Window_(d, iFalse); | ||
498 | /* Load the border shadow texture. */ { | 519 | /* Load the border shadow texture. */ { |
499 | SDL_Surface *surf = loadImage_(&imageShadow_Embedded, 0); | 520 | SDL_Surface *surf = loadImage_(&imageShadow_Embedded, 0); |
500 | d->borderShadow = SDL_CreateTextureFromSurface(d->render, surf); | 521 | d->base.borderShadow = SDL_CreateTextureFromSurface(d->base.render, surf); |
501 | SDL_SetTextureBlendMode(d->borderShadow, SDL_BLENDMODE_BLEND); | 522 | SDL_SetTextureBlendMode(d->base.borderShadow, SDL_BLENDMODE_BLEND); |
502 | free(surf->pixels); | 523 | free(surf->pixels); |
503 | SDL_FreeSurface(surf); | 524 | SDL_FreeSurface(surf); |
504 | } | 525 | } |
@@ -508,7 +529,7 @@ void init_Window(iWindow *d, iRect rect) { | |||
508 | if (prefs_App()->customFrame) { | 529 | if (prefs_App()->customFrame) { |
509 | SDL_Surface *surf = loadImage_(&imageLagrange64_Embedded, appIconSize_Root()); | 530 | SDL_Surface *surf = loadImage_(&imageLagrange64_Embedded, appIconSize_Root()); |
510 | SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); | 531 | SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); |
511 | d->appIcon = SDL_CreateTextureFromSurface(d->render, surf); | 532 | d->appIcon = SDL_CreateTextureFromSurface(d->base.render, surf); |
512 | free(surf->pixels); | 533 | free(surf->pixels); |
513 | SDL_FreeSurface(surf); | 534 | SDL_FreeSurface(surf); |
514 | /* We need to observe non-client-area events. */ | 535 | /* We need to observe non-client-area events. */ |
@@ -517,7 +538,7 @@ void init_Window(iWindow *d, iRect rect) { | |||
517 | #endif | 538 | #endif |
518 | } | 539 | } |
519 | 540 | ||
520 | void deinit_Window(iWindow *d) { | 541 | static void deinitRoots_Window_(iWindow *d) { |
521 | iRecycle(); | 542 | iRecycle(); |
522 | iForIndices(i, d->roots) { | 543 | iForIndices(i, d->roots) { |
523 | if (d->roots[i]) { | 544 | if (d->roots[i]) { |
@@ -525,19 +546,17 @@ void deinit_Window(iWindow *d) { | |||
525 | deinit_Root(d->roots[i]); | 546 | deinit_Root(d->roots[i]); |
526 | } | 547 | } |
527 | } | 548 | } |
528 | if (theWindow_ == d) { | 549 | setCurrent_Root(NULL); |
550 | } | ||
551 | |||
552 | void deinit_MainWindow(iMainWindow *d) { | ||
553 | deinitRoots_Window_(as_Window(d)); | ||
554 | if (theWindow_ == as_Window(d)) { | ||
529 | theWindow_ = NULL; | 555 | theWindow_ = NULL; |
530 | } | 556 | } |
531 | setCurrent_Root(NULL); | ||
532 | delete_String(d->pendingSplitUrl); | 557 | delete_String(d->pendingSplitUrl); |
533 | deinit_Text(); | 558 | deinit_Text(); |
534 | SDL_DestroyRenderer(d->render); | 559 | deinit_Window(&d->base); |
535 | SDL_DestroyWindow(d->win); | ||
536 | iForIndices(i, d->cursors) { | ||
537 | if (d->cursors[i]) { | ||
538 | SDL_FreeCursor(d->cursors[i]); | ||
539 | } | ||
540 | } | ||
541 | } | 560 | } |
542 | 561 | ||
543 | SDL_Renderer *renderer_Window(const iWindow *d) { | 562 | SDL_Renderer *renderer_Window(const iWindow *d) { |
@@ -550,8 +569,8 @@ iInt2 maxTextureSize_Window(const iWindow *d) { | |||
550 | return init_I2(info.max_texture_width, info.max_texture_height); | 569 | return init_I2(info.max_texture_width, info.max_texture_height); |
551 | } | 570 | } |
552 | 571 | ||
553 | iBool isFullscreen_Window(const iWindow *d) { | 572 | iBool isFullscreen_MainWindow(const iMainWindow *d) { |
554 | return snap_Window(d) == fullscreen_WindowSnap; | 573 | return snap_MainWindow(d) == fullscreen_WindowSnap; |
555 | } | 574 | } |
556 | 575 | ||
557 | iRoot *findRoot_Window(const iWindow *d, const iWidget *widget) { | 576 | iRoot *findRoot_Window(const iWindow *d, const iWidget *widget) { |
@@ -570,36 +589,41 @@ iRoot *otherRoot_Window(const iWindow *d, iRoot *root) { | |||
570 | return root == d->roots[0] && d->roots[1] ? d->roots[1] : d->roots[0]; | 589 | return root == d->roots[0] && d->roots[1] ? d->roots[1] : d->roots[0]; |
571 | } | 590 | } |
572 | 591 | ||
573 | static void invalidate_Window_(iWindow *d, iBool forced) { | 592 | static void invalidate_MainWindow_(iMainWindow *d, iBool forced) { |
574 | if (d && (!d->isInvalidated || forced)) { | 593 | if (d && (!d->base.isInvalidated || forced)) { |
575 | d->isInvalidated = iTrue; | 594 | d->base.isInvalidated = iTrue; |
576 | resetFonts_Text(); | 595 | resetFonts_Text(); |
577 | postCommand_App("theme.changed auto:1"); /* forces UI invalidation */ | 596 | postCommand_App("theme.changed auto:1"); /* forces UI invalidation */ |
578 | } | 597 | } |
579 | } | 598 | } |
580 | 599 | ||
581 | void invalidate_Window(iWindow *d) { | 600 | void invalidate_Window(iAnyWindow *d) { |
582 | invalidate_Window_(d, iFalse); | 601 | if (type_Window(d) == main_WindowType) { |
602 | invalidate_MainWindow_(as_MainWindow(d), iFalse); | ||
603 | } | ||
604 | else { | ||
605 | iAssert(type_Window(d) == main_WindowType); | ||
606 | } | ||
583 | } | 607 | } |
584 | 608 | ||
585 | static iBool isNormalPlacement_Window_(const iWindow *d) { | 609 | static iBool isNormalPlacement_MainWindow_(const iMainWindow *d) { |
586 | if (d->isDrawFrozen) return iFalse; | 610 | if (d->base.isDrawFrozen) return iFalse; |
587 | #if defined (iPlatformApple) | 611 | #if defined (iPlatformApple) |
588 | /* Maximized mode is not special on macOS. */ | 612 | /* Maximized mode is not special on macOS. */ |
589 | if (snap_Window(d) == maximized_WindowSnap) { | 613 | if (snap_MainWindow(d) == maximized_WindowSnap) { |
590 | return iTrue; | 614 | return iTrue; |
591 | } | 615 | } |
592 | #endif | 616 | #endif |
593 | if (snap_Window(d)) return iFalse; | 617 | if (snap_MainWindow(d)) return iFalse; |
594 | return !(SDL_GetWindowFlags(d->win) & SDL_WINDOW_MINIMIZED); | 618 | return !(SDL_GetWindowFlags(d->base.win) & SDL_WINDOW_MINIMIZED); |
595 | } | 619 | } |
596 | 620 | ||
597 | static iBool unsnap_Window_(iWindow *d, const iInt2 *newPos) { | 621 | static iBool unsnap_MainWindow_(iMainWindow *d, const iInt2 *newPos) { |
598 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) | 622 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) |
599 | if (!prefs_App()->customFrame) { | 623 | if (!prefs_App()->customFrame) { |
600 | return iFalse; | 624 | return iFalse; |
601 | } | 625 | } |
602 | const int snap = snap_Window(d); | 626 | const int snap = snap_MainWindow(d); |
603 | if (snap == yMaximized_WindowSnap || snap == left_WindowSnap || snap == right_WindowSnap) { | 627 | if (snap == yMaximized_WindowSnap || snap == left_WindowSnap || snap == right_WindowSnap) { |
604 | if (!newPos || (d->place.lastHit == SDL_HITTEST_RESIZE_LEFT || | 628 | if (!newPos || (d->place.lastHit == SDL_HITTEST_RESIZE_LEFT || |
605 | d->place.lastHit == SDL_HITTEST_RESIZE_RIGHT)) { | 629 | d->place.lastHit == SDL_HITTEST_RESIZE_RIGHT)) { |
@@ -607,21 +631,21 @@ static iBool unsnap_Window_(iWindow *d, const iInt2 *newPos) { | |||
607 | } | 631 | } |
608 | if (newPos) { | 632 | if (newPos) { |
609 | SDL_Rect usable; | 633 | SDL_Rect usable; |
610 | SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->win), &usable); | 634 | SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->base.win), &usable); |
611 | /* Snap to top. */ | 635 | /* Snap to top. */ |
612 | if (snap == yMaximized_WindowSnap && | 636 | if (snap == yMaximized_WindowSnap && |
613 | iAbs(newPos->y - usable.y) < lineHeight_Text(uiContent_FontId) * 2) { | 637 | iAbs(newPos->y - usable.y) < lineHeight_Text(uiContent_FontId) * 2) { |
614 | setSnap_Window(d, redo_WindowSnap | yMaximized_WindowSnap); | 638 | setSnap_MainWindow(d, redo_WindowSnap | yMaximized_WindowSnap); |
615 | return iFalse; | 639 | return iFalse; |
616 | } | 640 | } |
617 | } | 641 | } |
618 | } | 642 | } |
619 | if (snap && snap != fullscreen_WindowSnap) { | 643 | if (snap && snap != fullscreen_WindowSnap) { |
620 | if (snap_Window(d) == yMaximized_WindowSnap && newPos) { | 644 | if (snap_MainWindow(d) == yMaximized_WindowSnap && newPos) { |
621 | d->place.normalRect.pos = *newPos; | 645 | d->place.normalRect.pos = *newPos; |
622 | } | 646 | } |
623 | //printf("unsnap\n"); fflush(stdout); | 647 | //printf("unsnap\n"); fflush(stdout); |
624 | setSnap_Window(d, none_WindowSnap); | 648 | setSnap_MainWindow(d, none_WindowSnap); |
625 | return iTrue; | 649 | return iTrue; |
626 | } | 650 | } |
627 | #endif | 651 | #endif |
@@ -652,109 +676,110 @@ static void checkPixelRatioChange_Window_(iWindow *d) { | |||
652 | } | 676 | } |
653 | } | 677 | } |
654 | 678 | ||
655 | static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) { | 679 | static iBool handleWindowEvent_MainWindow_(iMainWindow *d, const SDL_WindowEvent *ev) { |
656 | switch (ev->event) { | 680 | switch (ev->event) { |
657 | #if defined (iPlatformDesktop) | 681 | #if defined(iPlatformDesktop) |
658 | case SDL_WINDOWEVENT_EXPOSED: | 682 | case SDL_WINDOWEVENT_EXPOSED: |
659 | if (!d->isExposed) { | 683 | if (!d->base.isExposed) { |
660 | drawBlank_Window_(d); /* avoid showing system-provided contents */ | 684 | drawBlank_Window_(as_Window(d)); /* avoid showing system-provided contents */ |
661 | d->isExposed = iTrue; | 685 | d->base.isExposed = iTrue; |
662 | } | 686 | } |
663 | /* Since we are manually controlling when to redraw the window, we are responsible | 687 | /* Since we are manually controlling when to redraw the window, we are responsible |
664 | for ensuring that window contents get redrawn after expose events. Under certain | 688 | for ensuring that window contents get redrawn after expose events. Under certain |
665 | circumstances (e.g., under openbox), not doing this would mean that the window | 689 | circumstances (e.g., under openbox), not doing this would mean that the window |
666 | is missing contents until other events trigger a refresh. */ | 690 | is missing contents until other events trigger a refresh. */ |
667 | postRefresh_App(); | 691 | postRefresh_App(); |
668 | #if defined (LAGRANGE_ENABLE_WINDOWPOS_FIX) | 692 | #if defined(LAGRANGE_ENABLE_WINDOWPOS_FIX) |
669 | if (d->place.initialPos.x >= 0) { | 693 | if (d->place.initialPos.x >= 0) { |
670 | int bx, by; | 694 | int bx, by; |
671 | SDL_GetWindowBordersSize(d->win, &by, &bx, NULL, NULL); | 695 | SDL_GetWindowBordersSize(d->win, &by, &bx, NULL, NULL); |
672 | SDL_SetWindowPosition(d->win, d->place.initialPos.x + bx, d->place.initialPos.y + by); | 696 | SDL_SetWindowPosition( |
697 | d->win, d->place.initialPos.x + bx, d->place.initialPos.y + by); | ||
673 | d->place.initialPos = init1_I2(-1); | 698 | d->place.initialPos = init1_I2(-1); |
674 | } | 699 | } |
675 | #endif | 700 | #endif |
676 | return iFalse; | 701 | return iFalse; |
677 | case SDL_WINDOWEVENT_MOVED: { | 702 | case SDL_WINDOWEVENT_MOVED: { |
678 | if (d->isMinimized) { | 703 | if (d->base.isMinimized) { |
679 | return iFalse; | 704 | return iFalse; |
680 | } | 705 | } |
681 | checkPixelRatioChange_Window_(d); | 706 | checkPixelRatioChange_Window_(as_Window(d)); |
682 | const iInt2 newPos = init_I2(ev->data1, ev->data2); | 707 | const iInt2 newPos = init_I2(ev->data1, ev->data2); |
683 | if (isEqual_I2(newPos, init1_I2(-32000))) { /* magic! */ | 708 | if (isEqual_I2(newPos, init1_I2(-32000))) { /* magic! */ |
684 | /* Maybe minimized? Seems like a Windows constant of some kind. */ | 709 | /* Maybe minimized? Seems like a Windows constant of some kind. */ |
685 | d->isMinimized = iTrue; | 710 | d->base.isMinimized = iTrue; |
686 | return iFalse; | 711 | return iFalse; |
687 | } | 712 | } |
688 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) | 713 | #if defined(LAGRANGE_ENABLE_CUSTOM_FRAME) |
689 | /* Set the snap position depending on where the mouse cursor is. */ | 714 | /* Set the snap position depending on where the mouse cursor is. */ |
690 | if (prefs_App()->customFrame) { | 715 | if (prefs_App()->customFrame) { |
691 | SDL_Rect usable; | 716 | SDL_Rect usable; |
692 | iInt2 mouse = cursor_Win32(); /* SDL is unaware of the current cursor pos */ | 717 | iInt2 mouse = cursor_Win32(); /* SDL is unaware of the current cursor pos */ |
693 | SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->win), &usable); | 718 | SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->base.win), &usable); |
694 | const iBool isTop = iAbs(mouse.y - usable.y) < gap_UI * 20; | 719 | const iBool isTop = iAbs(mouse.y - usable.y) < gap_UI * 20; |
695 | const iBool isBottom = iAbs(usable.y + usable.h - mouse.y) < gap_UI * 20; | 720 | const iBool isBottom = iAbs(usable.y + usable.h - mouse.y) < gap_UI * 20; |
696 | if (iAbs(mouse.x - usable.x) < gap_UI) { | 721 | if (iAbs(mouse.x - usable.x) < gap_UI) { |
697 | setSnap_Window(d, | 722 | setSnap_MainWindow(d, |
698 | redo_WindowSnap | left_WindowSnap | | 723 | redo_WindowSnap | left_WindowSnap | |
699 | (isTop ? topBit_WindowSnap : 0) | | 724 | (isTop ? topBit_WindowSnap : 0) | |
700 | (isBottom ? bottomBit_WindowSnap : 0)); | 725 | (isBottom ? bottomBit_WindowSnap : 0)); |
701 | return iTrue; | 726 | return iTrue; |
702 | } | 727 | } |
703 | if (iAbs(mouse.x - usable.x - usable.w) < gap_UI) { | 728 | if (iAbs(mouse.x - usable.x - usable.w) < gap_UI) { |
704 | setSnap_Window(d, | 729 | setSnap_MainWindow(d, |
705 | redo_WindowSnap | right_WindowSnap | | 730 | redo_WindowSnap | right_WindowSnap | |
706 | (isTop ? topBit_WindowSnap : 0) | | 731 | (isTop ? topBit_WindowSnap : 0) | |
707 | (isBottom ? bottomBit_WindowSnap : 0)); | 732 | (isBottom ? bottomBit_WindowSnap : 0)); |
708 | return iTrue; | 733 | return iTrue; |
709 | } | 734 | } |
710 | if (iAbs(mouse.y - usable.y) < 2) { | 735 | if (iAbs(mouse.y - usable.y) < 2) { |
711 | setSnap_Window(d, | 736 | setSnap_MainWindow(d, |
712 | redo_WindowSnap | (d->place.lastHit == SDL_HITTEST_RESIZE_TOP | 737 | redo_WindowSnap | (d->place.lastHit == SDL_HITTEST_RESIZE_TOP |
713 | ? yMaximized_WindowSnap | 738 | ? yMaximized_WindowSnap |
714 | : maximized_WindowSnap)); | 739 | : maximized_WindowSnap)); |
715 | return iTrue; | 740 | return iTrue; |
716 | } | 741 | } |
717 | } | 742 | } |
718 | #endif /* defined LAGRANGE_ENABLE_CUSTOM_FRAME */ | 743 | #endif /* defined LAGRANGE_ENABLE_CUSTOM_FRAME */ |
719 | if (unsnap_Window_(d, &newPos)) { | 744 | if (unsnap_MainWindow_(d, &newPos)) { |
720 | return iTrue; | 745 | return iTrue; |
721 | } | 746 | } |
722 | if (isNormalPlacement_Window_(d)) { | 747 | if (isNormalPlacement_MainWindow_(d)) { |
723 | d->place.normalRect.pos = newPos; | 748 | d->place.normalRect.pos = newPos; |
724 | //printf("normal rect set (move)\n"); fflush(stdout); | 749 | // printf("normal rect set (move)\n"); fflush(stdout); |
725 | iInt2 border = zero_I2(); | 750 | iInt2 border = zero_I2(); |
726 | #if !defined (iPlatformApple) | 751 | #if !defined(iPlatformApple) |
727 | SDL_GetWindowBordersSize(d->win, &border.y, &border.x, NULL, NULL); | 752 | SDL_GetWindowBordersSize(d->win, &border.y, &border.x, NULL, NULL); |
728 | #endif | 753 | #endif |
729 | d->place.normalRect.pos = max_I2(zero_I2(), sub_I2(d->place.normalRect.pos, border)); | 754 | d->place.normalRect.pos = |
755 | max_I2(zero_I2(), sub_I2(d->place.normalRect.pos, border)); | ||
730 | } | 756 | } |
731 | return iTrue; | 757 | return iTrue; |
732 | } | 758 | } |
733 | case SDL_WINDOWEVENT_RESIZED: | 759 | case SDL_WINDOWEVENT_RESIZED: |
734 | if (d->isMinimized) { | 760 | if (d->base.isMinimized) { |
735 | //updateSize_Window_(d, iTrue); | 761 | // updateSize_Window_(d, iTrue); |
736 | return iTrue; | 762 | return iTrue; |
737 | } | 763 | } |
738 | if (unsnap_Window_(d, NULL)) { | 764 | if (unsnap_MainWindow_(d, NULL)) { |
739 | return iTrue; | 765 | return iTrue; |
740 | } | 766 | } |
741 | if (isNormalPlacement_Window_(d)) { | 767 | if (isNormalPlacement_MainWindow_(d)) { |
742 | d->place.normalRect.size = init_I2(ev->data1, ev->data2); | 768 | d->place.normalRect.size = init_I2(ev->data1, ev->data2); |
743 | //printf("normal rect set (resize)\n"); fflush(stdout); | 769 | // printf("normal rect set (resize)\n"); fflush(stdout); |
744 | } | 770 | } |
745 | checkPixelRatioChange_Window_(d); | 771 | checkPixelRatioChange_Window_(as_Window(d)); |
746 | //updateSize_Window_(d, iTrue /* we were already redrawing during the resize */); | ||
747 | postRefresh_App(); | 772 | postRefresh_App(); |
748 | return iTrue; | 773 | return iTrue; |
749 | case SDL_WINDOWEVENT_RESTORED: | 774 | case SDL_WINDOWEVENT_RESTORED: |
750 | case SDL_WINDOWEVENT_SHOWN: | 775 | case SDL_WINDOWEVENT_SHOWN: |
751 | updateSize_Window_(d, iTrue); | 776 | updateSize_MainWindow_(d, iTrue); |
752 | invalidate_Window_(d, iTrue); | 777 | invalidate_MainWindow_(d, iTrue); |
753 | d->isMinimized = iFalse; | 778 | d->base.isMinimized = iFalse; |
754 | postRefresh_App(); | 779 | postRefresh_App(); |
755 | return iTrue; | 780 | return iTrue; |
756 | case SDL_WINDOWEVENT_MINIMIZED: | 781 | case SDL_WINDOWEVENT_MINIMIZED: |
757 | d->isMinimized = iTrue; | 782 | d->base.isMinimized = iTrue; |
758 | return iTrue; | 783 | return iTrue; |
759 | #else /* if defined (!iPlatformDesktop) */ | 784 | #else /* if defined (!iPlatformDesktop) */ |
760 | case SDL_WINDOWEVENT_RESIZED: | 785 | case SDL_WINDOWEVENT_RESIZED: |
@@ -765,19 +790,19 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) { | |||
765 | #endif | 790 | #endif |
766 | case SDL_WINDOWEVENT_LEAVE: | 791 | case SDL_WINDOWEVENT_LEAVE: |
767 | unhover_Widget(); | 792 | unhover_Widget(); |
768 | d->isMouseInside = iFalse; | 793 | d->base.isMouseInside = iFalse; |
769 | postCommand_App("window.mouse.exited"); | 794 | postCommand_App("window.mouse.exited"); |
770 | return iTrue; | 795 | return iTrue; |
771 | case SDL_WINDOWEVENT_ENTER: | 796 | case SDL_WINDOWEVENT_ENTER: |
772 | d->isMouseInside = iTrue; | 797 | d->base.isMouseInside = iTrue; |
773 | postCommand_App("window.mouse.entered"); | 798 | postCommand_App("window.mouse.entered"); |
774 | return iTrue; | 799 | return iTrue; |
775 | case SDL_WINDOWEVENT_FOCUS_GAINED: | 800 | case SDL_WINDOWEVENT_FOCUS_GAINED: |
776 | d->focusGainedAt = SDL_GetTicks(); | 801 | d->base.focusGainedAt = SDL_GetTicks(); |
777 | setCapsLockDown_Keys(iFalse); | 802 | setCapsLockDown_Keys(iFalse); |
778 | postCommand_App("window.focus.gained"); | 803 | postCommand_App("window.focus.gained"); |
779 | d->isExposed = iTrue; | 804 | d->base.isExposed = iTrue; |
780 | #if !defined (iPlatformDesktop) | 805 | #if !defined(iPlatformDesktop) |
781 | /* Returned to foreground, may have lost buffered content. */ | 806 | /* Returned to foreground, may have lost buffered content. */ |
782 | invalidate_Window_(d, iTrue); | 807 | invalidate_Window_(d, iTrue); |
783 | postCommand_App("window.unfreeze"); | 808 | postCommand_App("window.unfreeze"); |
@@ -785,12 +810,12 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) { | |||
785 | return iFalse; | 810 | return iFalse; |
786 | case SDL_WINDOWEVENT_FOCUS_LOST: | 811 | case SDL_WINDOWEVENT_FOCUS_LOST: |
787 | postCommand_App("window.focus.lost"); | 812 | postCommand_App("window.focus.lost"); |
788 | #if !defined (iPlatformDesktop) | 813 | #if !defined(iPlatformDesktop) |
789 | setFreezeDraw_Window(d, iTrue); | 814 | setFreezeDraw_Window(d, iTrue); |
790 | #endif | 815 | #endif |
791 | return iFalse; | 816 | return iFalse; |
792 | case SDL_WINDOWEVENT_TAKE_FOCUS: | 817 | case SDL_WINDOWEVENT_TAKE_FOCUS: |
793 | SDL_SetWindowInputFocus(d->win); | 818 | SDL_SetWindowInputFocus(d->base.win); |
794 | postRefresh_App(); | 819 | postRefresh_App(); |
795 | return iTrue; | 820 | return iTrue; |
796 | default: | 821 | default: |
@@ -806,7 +831,8 @@ static void applyCursor_Window_(iWindow *d) { | |||
806 | } | 831 | } |
807 | } | 832 | } |
808 | 833 | ||
809 | iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { | 834 | iBool processEvent_MainWindow(iMainWindow *d, const SDL_Event *ev) { |
835 | iWindow *w = as_Window(d); | ||
810 | switch (ev->type) { | 836 | switch (ev->type) { |
811 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) | 837 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) |
812 | case SDL_SYSWMEVENT: { | 838 | case SDL_SYSWMEVENT: { |
@@ -819,19 +845,19 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { | |||
819 | } | 845 | } |
820 | #endif | 846 | #endif |
821 | case SDL_WINDOWEVENT: { | 847 | case SDL_WINDOWEVENT: { |
822 | return handleWindowEvent_Window_(d, &ev->window); | 848 | return handleWindowEvent_MainWindow_(d, &ev->window); |
823 | } | 849 | } |
824 | case SDL_RENDER_TARGETS_RESET: | 850 | case SDL_RENDER_TARGETS_RESET: |
825 | case SDL_RENDER_DEVICE_RESET: { | 851 | case SDL_RENDER_DEVICE_RESET: { |
826 | invalidate_Window_(d, iTrue /* force full reset */); | 852 | invalidate_MainWindow_(d, iTrue /* force full reset */); |
827 | break; | 853 | break; |
828 | } | 854 | } |
829 | default: { | 855 | default: { |
830 | SDL_Event event = *ev; | 856 | SDL_Event event = *ev; |
831 | if (event.type == SDL_USEREVENT && isCommand_UserEvent(ev, "window.unfreeze")) { | 857 | if (event.type == SDL_USEREVENT && isCommand_UserEvent(ev, "window.unfreeze")) { |
832 | d->isDrawFrozen = iFalse; | 858 | d->base.isDrawFrozen = iFalse; |
833 | if (SDL_GetWindowFlags(d->win) & SDL_WINDOW_HIDDEN) { | 859 | if (SDL_GetWindowFlags(w->win) & SDL_WINDOW_HIDDEN) { |
834 | SDL_ShowWindow(d->win); | 860 | SDL_ShowWindow(w->win); |
835 | } | 861 | } |
836 | postRefresh_App(); | 862 | postRefresh_App(); |
837 | postCommand_App("media.player.update"); /* in case a player needs updating */ | 863 | postCommand_App("media.player.update"); /* in case a player needs updating */ |
@@ -840,35 +866,35 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { | |||
840 | if (processEvent_Touch(&event)) { | 866 | if (processEvent_Touch(&event)) { |
841 | return iTrue; | 867 | return iTrue; |
842 | } | 868 | } |
843 | if (event.type == SDL_KEYDOWN && SDL_GetTicks() - d->focusGainedAt < 10) { | 869 | if (event.type == SDL_KEYDOWN && SDL_GetTicks() - d->base.focusGainedAt < 10) { |
844 | /* Suspiciously close to when input focus was received. For example under openbox, | 870 | /* Suspiciously close to when input focus was received. For example under openbox, |
845 | closing xterm with Ctrl+D will cause the keydown event to "spill" over to us. | 871 | closing xterm with Ctrl+D will cause the keydown event to "spill" over to us. |
846 | As a workaround, ignore these events. */ | 872 | As a workaround, ignore these events. */ |
847 | return iTrue; /* won't go to bindings, either */ | 873 | return iTrue; /* won't go to bindings, either */ |
848 | } | 874 | } |
849 | if (event.type == SDL_MOUSEBUTTONDOWN && d->ignoreClick) { | 875 | if (event.type == SDL_MOUSEBUTTONDOWN && d->base.ignoreClick) { |
850 | d->ignoreClick = iFalse; | 876 | d->base.ignoreClick = iFalse; |
851 | return iTrue; | 877 | return iTrue; |
852 | } | 878 | } |
853 | /* Map mouse pointer coordinate to our coordinate system. */ | 879 | /* Map mouse pointer coordinate to our coordinate system. */ |
854 | if (event.type == SDL_MOUSEMOTION) { | 880 | if (event.type == SDL_MOUSEMOTION) { |
855 | setCursor_Window(d, SDL_SYSTEM_CURSOR_ARROW); /* default cursor */ | 881 | setCursor_Window(w, SDL_SYSTEM_CURSOR_ARROW); /* default cursor */ |
856 | const iInt2 pos = coord_Window(d, event.motion.x, event.motion.y); | 882 | const iInt2 pos = coord_Window(w, event.motion.x, event.motion.y); |
857 | event.motion.x = pos.x; | 883 | event.motion.x = pos.x; |
858 | event.motion.y = pos.y; | 884 | event.motion.y = pos.y; |
859 | } | 885 | } |
860 | else if (event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEBUTTONDOWN) { | 886 | else if (event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEBUTTONDOWN) { |
861 | const iInt2 pos = coord_Window(d, event.button.x, event.button.y); | 887 | const iInt2 pos = coord_Window(w, event.button.x, event.button.y); |
862 | event.button.x = pos.x; | 888 | event.button.x = pos.x; |
863 | event.button.y = pos.y; | 889 | event.button.y = pos.y; |
864 | if (event.type == SDL_MOUSEBUTTONDOWN) { | 890 | if (event.type == SDL_MOUSEBUTTONDOWN) { |
865 | /* Button clicks will change keyroot. */ | 891 | /* Button clicks will change keyroot. */ |
866 | if (numRoots_Window(d) > 1) { | 892 | if (numRoots_Window(w) > 1) { |
867 | const iInt2 click = init_I2(event.button.x, event.button.y); | 893 | const iInt2 click = init_I2(event.button.x, event.button.y); |
868 | iForIndices(i, d->roots) { | 894 | iForIndices(i, w->roots) { |
869 | iRoot *root = d->roots[i]; | 895 | iRoot *root = w->roots[i]; |
870 | if (root != d->keyRoot && contains_Rect(rect_Root(root), click)) { | 896 | if (root != w->keyRoot && contains_Rect(rect_Root(root), click)) { |
871 | setKeyRoot_Window(d, root); | 897 | setKeyRoot_Window(w, root); |
872 | break; | 898 | break; |
873 | } | 899 | } |
874 | } | 900 | } |
@@ -883,13 +909,13 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { | |||
883 | event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEBUTTONDOWN) { | 909 | event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEBUTTONDOWN) { |
884 | if (mouseGrab_Widget()) { | 910 | if (mouseGrab_Widget()) { |
885 | iWidget *grabbed = mouseGrab_Widget(); | 911 | iWidget *grabbed = mouseGrab_Widget(); |
886 | setCurrent_Root(findRoot_Window(d, grabbed)); | 912 | setCurrent_Root(findRoot_Window(w, grabbed)); |
887 | wasUsed = dispatchEvent_Widget(grabbed, &event); | 913 | wasUsed = dispatchEvent_Widget(grabbed, &event); |
888 | } | 914 | } |
889 | } | 915 | } |
890 | /* Dispatch the event to the tree of widgets. */ | 916 | /* Dispatch the event to the tree of widgets. */ |
891 | if (!wasUsed) { | 917 | if (!wasUsed) { |
892 | wasUsed = dispatchEvent_Window(d, &event); | 918 | wasUsed = dispatchEvent_Window(w, &event); |
893 | } | 919 | } |
894 | if (!wasUsed) { | 920 | if (!wasUsed) { |
895 | /* As a special case, clicking the middle mouse button can be used for pasting | 921 | /* As a special case, clicking the middle mouse button can be used for pasting |
@@ -902,17 +928,17 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { | |||
902 | paste.key.keysym.mod = KMOD_PRIMARY; | 928 | paste.key.keysym.mod = KMOD_PRIMARY; |
903 | paste.key.state = SDL_PRESSED; | 929 | paste.key.state = SDL_PRESSED; |
904 | paste.key.timestamp = SDL_GetTicks(); | 930 | paste.key.timestamp = SDL_GetTicks(); |
905 | wasUsed = dispatchEvent_Window(d, &paste); | 931 | wasUsed = dispatchEvent_Window(w, &paste); |
906 | } | 932 | } |
907 | if (event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_RIGHT) { | 933 | if (event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_RIGHT) { |
908 | if (postContextClick_Window(d, &event.button)) { | 934 | if (postContextClick_Window(w, &event.button)) { |
909 | wasUsed = iTrue; | 935 | wasUsed = iTrue; |
910 | } | 936 | } |
911 | } | 937 | } |
912 | } | 938 | } |
913 | if (isMetricsChange_UserEvent(&event)) { | 939 | if (isMetricsChange_UserEvent(&event)) { |
914 | iForIndices(i, d->roots) { | 940 | iForIndices(i, w->roots) { |
915 | updateMetrics_Root(d->roots[i]); | 941 | updateMetrics_Root(w->roots[i]); |
916 | } | 942 | } |
917 | } | 943 | } |
918 | if (isCommand_UserEvent(&event, "lang.changed")) { | 944 | if (isCommand_UserEvent(&event, "lang.changed")) { |
@@ -921,16 +947,16 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { | |||
921 | removeMacMenus_(); | 947 | removeMacMenus_(); |
922 | insertMacMenus_(); | 948 | insertMacMenus_(); |
923 | #endif | 949 | #endif |
924 | invalidate_Window(d); | 950 | invalidate_Window(w); |
925 | iForIndices(i, d->roots) { | 951 | iForIndices(i, w->roots) { |
926 | if (d->roots[i]) { | 952 | if (w->roots[i]) { |
927 | updatePreferencesLayout_Widget(findChild_Widget(d->roots[i]->widget, "prefs")); | 953 | updatePreferencesLayout_Widget(findChild_Widget(w->roots[i]->widget, "prefs")); |
928 | arrange_Widget(d->roots[i]->widget); | 954 | arrange_Widget(w->roots[i]->widget); |
929 | } | 955 | } |
930 | } | 956 | } |
931 | } | 957 | } |
932 | if (event.type == SDL_MOUSEMOTION) { | 958 | if (event.type == SDL_MOUSEMOTION) { |
933 | applyCursor_Window_(d); | 959 | applyCursor_Window_(w); |
934 | } | 960 | } |
935 | return wasUsed; | 961 | return wasUsed; |
936 | } | 962 | } |
@@ -1018,25 +1044,26 @@ iBool postContextClick_Window(iWindow *d, const SDL_MouseButtonEvent *ev) { | |||
1018 | return iFalse; | 1044 | return iFalse; |
1019 | } | 1045 | } |
1020 | 1046 | ||
1021 | void draw_Window(iWindow *d) { | 1047 | void draw_MainWindow(iMainWindow *d) { |
1022 | if (d->isDrawFrozen) { | 1048 | iWindow *w = as_Window(d); |
1049 | if (w->isDrawFrozen) { | ||
1023 | return; | 1050 | return; |
1024 | } | 1051 | } |
1025 | /* Check if root needs resizing. */ { | 1052 | /* Check if root needs resizing. */ { |
1026 | iInt2 renderSize; | 1053 | iInt2 renderSize; |
1027 | SDL_GetRendererOutputSize(d->render, &renderSize.x, &renderSize.y); | 1054 | SDL_GetRendererOutputSize(w->render, &renderSize.x, &renderSize.y); |
1028 | if (!isEqual_I2(renderSize, d->size)) { | 1055 | if (!isEqual_I2(renderSize, w->size)) { |
1029 | updateSize_Window_(d, iTrue); | 1056 | updateSize_MainWindow_(d, iTrue); |
1030 | processEvents_App(postedEventsOnly_AppEventMode); | 1057 | processEvents_App(postedEventsOnly_AppEventMode); |
1031 | } | 1058 | } |
1032 | } | 1059 | } |
1033 | const int winFlags = SDL_GetWindowFlags(d->win); | 1060 | const int winFlags = SDL_GetWindowFlags(d->base.win); |
1034 | const iBool gotFocus = (winFlags & SDL_WINDOW_INPUT_FOCUS) != 0; | 1061 | const iBool gotFocus = (winFlags & SDL_WINDOW_INPUT_FOCUS) != 0; |
1035 | iPaint p; | 1062 | iPaint p; |
1036 | init_Paint(&p); | 1063 | init_Paint(&p); |
1037 | /* Clear the window. The clear color is visible as a border around the window | 1064 | /* Clear the window. The clear color is visible as a border around the window |
1038 | when the custom frame is being used. */ { | 1065 | when the custom frame is being used. */ { |
1039 | setCurrent_Root(d->roots[0]); | 1066 | setCurrent_Root(w->roots[0]); |
1040 | #if defined (iPlatformMobile) | 1067 | #if defined (iPlatformMobile) |
1041 | iColor back = get_Color(uiBackground_ColorId); | 1068 | iColor back = get_Color(uiBackground_ColorId); |
1042 | if (deviceType_App() == phone_AppDeviceType) { | 1069 | if (deviceType_App() == phone_AppDeviceType) { |
@@ -1050,16 +1077,16 @@ void draw_Window(iWindow *d) { | |||
1050 | : uiSeparator_ColorId); | 1077 | : uiSeparator_ColorId); |
1051 | #endif | 1078 | #endif |
1052 | unsetClip_Paint(&p); /* update clip to full window */ | 1079 | unsetClip_Paint(&p); /* update clip to full window */ |
1053 | SDL_SetRenderDrawColor(d->render, back.r, back.g, back.b, 255); | 1080 | SDL_SetRenderDrawColor(w->render, back.r, back.g, back.b, 255); |
1054 | SDL_RenderClear(d->render); | 1081 | SDL_RenderClear(w->render); |
1055 | } | 1082 | } |
1056 | /* Draw widgets. */ | 1083 | /* Draw widgets. */ |
1057 | d->frameTime = SDL_GetTicks(); | 1084 | w->frameTime = SDL_GetTicks(); |
1058 | if (isExposed_Window(d)) { | 1085 | if (isExposed_Window(w)) { |
1059 | d->isInvalidated = iFalse; | 1086 | w->isInvalidated = iFalse; |
1060 | extern int drawCount_; | 1087 | extern int drawCount_; |
1061 | iForIndices(i, d->roots) { | 1088 | iForIndices(i, w->roots) { |
1062 | iRoot *root = d->roots[i]; | 1089 | iRoot *root = w->roots[i]; |
1063 | if (root) { | 1090 | if (root) { |
1064 | setCurrent_Root(root); | 1091 | setCurrent_Root(root); |
1065 | unsetClip_Paint(&p); /* update clip to current root */ | 1092 | unsetClip_Paint(&p); /* update clip to current root */ |
@@ -1076,14 +1103,14 @@ void draw_Window(iWindow *d) { | |||
1076 | SDL_SetTextureColorMod(d->appIcon, iconColor.r, iconColor.g, iconColor.b); | 1103 | SDL_SetTextureColorMod(d->appIcon, iconColor.r, iconColor.g, iconColor.b); |
1077 | SDL_SetTextureAlphaMod(d->appIcon, gotFocus || !isLight ? 255 : 92); | 1104 | SDL_SetTextureAlphaMod(d->appIcon, gotFocus || !isLight ? 255 : 92); |
1078 | SDL_RenderCopy( | 1105 | SDL_RenderCopy( |
1079 | d->render, | 1106 | w->render, |
1080 | d->appIcon, | 1107 | d->appIcon, |
1081 | NULL, | 1108 | NULL, |
1082 | &(SDL_Rect){ left_Rect(rect) + gap_UI * 1.25f, mid.y - size / 2, size, size }); | 1109 | &(SDL_Rect){ left_Rect(rect) + gap_UI * 1.25f, mid.y - size / 2, size, size }); |
1083 | } | 1110 | } |
1084 | #endif | 1111 | #endif |
1085 | /* Root separator and keyboard focus indicator. */ | 1112 | /* Root separator and keyboard focus indicator. */ |
1086 | if (numRoots_Window(d) > 1){ | 1113 | if (numRoots_Window(w) > 1){ |
1087 | const iRect bounds = bounds_Widget(root->widget); | 1114 | const iRect bounds = bounds_Widget(root->widget); |
1088 | if (i == 1) { | 1115 | if (i == 1) { |
1089 | fillRect_Paint(&p, (iRect){ | 1116 | fillRect_Paint(&p, (iRect){ |
@@ -1091,7 +1118,7 @@ void draw_Window(iWindow *d) { | |||
1091 | init_I2(gap_UI / 4, height_Rect(bounds)) | 1118 | init_I2(gap_UI / 4, height_Rect(bounds)) |
1092 | }, uiSeparator_ColorId); | 1119 | }, uiSeparator_ColorId); |
1093 | } | 1120 | } |
1094 | if (root == d->keyRoot) { | 1121 | if (root == w->keyRoot) { |
1095 | const iBool isDark = isDark_ColorTheme(colorTheme_App()); | 1122 | const iBool isDark = isDark_ColorTheme(colorTheme_App()); |
1096 | fillRect_Paint(&p, (iRect){ | 1123 | fillRect_Paint(&p, (iRect){ |
1097 | topLeft_Rect(bounds), | 1124 | topLeft_Rect(bounds), |
@@ -1104,7 +1131,7 @@ void draw_Window(iWindow *d) { | |||
1104 | } | 1131 | } |
1105 | setCurrent_Root(NULL); | 1132 | setCurrent_Root(NULL); |
1106 | #if !defined (NDEBUG) | 1133 | #if !defined (NDEBUG) |
1107 | draw_Text(defaultBold_FontId, safeRect_Root(d->roots[0]).pos, red_ColorId, "%d", drawCount_); | 1134 | draw_Text(defaultBold_FontId, safeRect_Root(w->roots[0]).pos, red_ColorId, "%d", drawCount_); |
1108 | drawCount_ = 0; | 1135 | drawCount_ = 0; |
1109 | #endif | 1136 | #endif |
1110 | } | 1137 | } |
@@ -1116,21 +1143,21 @@ void draw_Window(iWindow *d) { | |||
1116 | SDL_RenderCopy(d->render, glyphCache_Text(), NULL, &rect); | 1143 | SDL_RenderCopy(d->render, glyphCache_Text(), NULL, &rect); |
1117 | } | 1144 | } |
1118 | #endif | 1145 | #endif |
1119 | SDL_RenderPresent(d->render); | 1146 | SDL_RenderPresent(w->render); |
1120 | } | 1147 | } |
1121 | 1148 | ||
1122 | void resize_Window(iWindow *d, int w, int h) { | 1149 | void resize_MainWindow(iMainWindow *d, int w, int h) { |
1123 | if (w > 0 && h > 0) { | 1150 | if (w > 0 && h > 0) { |
1124 | SDL_SetWindowSize(d->win, w, h); | 1151 | SDL_SetWindowSize(d->base.win, w, h); |
1125 | updateSize_Window_(d, iFalse); | 1152 | updateSize_MainWindow_(d, iFalse); |
1126 | } | 1153 | } |
1127 | else { | 1154 | else { |
1128 | updateSize_Window_(d, iTrue); /* notify always */ | 1155 | updateSize_MainWindow_(d, iTrue); /* notify always */ |
1129 | } | 1156 | } |
1130 | } | 1157 | } |
1131 | 1158 | ||
1132 | void setTitle_Window(iWindow *d, const iString *title) { | 1159 | void setTitle_MainWindow(iMainWindow *d, const iString *title) { |
1133 | SDL_SetWindowTitle(d->win, cstr_String(title)); | 1160 | SDL_SetWindowTitle(d->base.win, cstr_String(title)); |
1134 | iLabelWidget *bar = findChild_Widget(get_Root()->widget, "winbar.title"); | 1161 | iLabelWidget *bar = findChild_Widget(get_Root()->widget, "winbar.title"); |
1135 | if (bar) { | 1162 | if (bar) { |
1136 | updateText_LabelWidget(bar, title); | 1163 | updateText_LabelWidget(bar, title); |
@@ -1204,11 +1231,15 @@ iWindow *get_Window(void) { | |||
1204 | return theWindow_; | 1231 | return theWindow_; |
1205 | } | 1232 | } |
1206 | 1233 | ||
1234 | iMainWindow *get_MainWindow(void) { | ||
1235 | return as_MainWindow(theWindow_); | ||
1236 | } | ||
1237 | |||
1207 | iBool isOpenGLRenderer_Window(void) { | 1238 | iBool isOpenGLRenderer_Window(void) { |
1208 | return isOpenGLRenderer_; | 1239 | return isOpenGLRenderer_; |
1209 | } | 1240 | } |
1210 | 1241 | ||
1211 | void setKeyboardHeight_Window(iWindow *d, int height) { | 1242 | void setKeyboardHeight_MainWindow(iMainWindow *d, int height) { |
1212 | if (d->keyboardHeight != height) { | 1243 | if (d->keyboardHeight != height) { |
1213 | d->keyboardHeight = height; | 1244 | d->keyboardHeight = height; |
1214 | postCommandf_App("keyboard.changed arg:%d", height); | 1245 | postCommandf_App("keyboard.changed arg:%d", height); |
@@ -1216,47 +1247,49 @@ void setKeyboardHeight_Window(iWindow *d, int height) { | |||
1216 | } | 1247 | } |
1217 | } | 1248 | } |
1218 | 1249 | ||
1219 | void checkPendingSplit_Window(iWindow *d) { | 1250 | void checkPendingSplit_MainWindow(iMainWindow *d) { |
1220 | if (d->splitMode != d->pendingSplitMode) { | 1251 | if (d->splitMode != d->pendingSplitMode) { |
1221 | setSplitMode_Window(d, d->pendingSplitMode); | 1252 | setSplitMode_MainWindow(d, d->pendingSplitMode); |
1222 | } | 1253 | } |
1223 | } | 1254 | } |
1224 | 1255 | ||
1225 | void swapRoots_Window(iWindow *d) { | 1256 | void swapRoots_MainWindow(iMainWindow *d) { |
1226 | if (numRoots_Window(d) == 2) { | 1257 | iWindow *w = as_Window(d); |
1227 | iSwap(iRoot *, d->roots[0], d->roots[1]); | 1258 | if (numRoots_Window(w) == 2) { |
1228 | updateSize_Window_(d, iTrue); | 1259 | iSwap(iRoot *, w->roots[0], w->roots[1]); |
1260 | updateSize_MainWindow_(d, iTrue); | ||
1229 | } | 1261 | } |
1230 | } | 1262 | } |
1231 | 1263 | ||
1232 | void setSplitMode_Window(iWindow *d, int splitFlags) { | 1264 | void setSplitMode_MainWindow(iMainWindow *d, int splitFlags) { |
1233 | const int splitMode = splitFlags & mode_WindowSplit; | 1265 | const int splitMode = splitFlags & mode_WindowSplit; |
1234 | if (deviceType_App() == phone_AppDeviceType) { | 1266 | if (deviceType_App() == phone_AppDeviceType) { |
1235 | /* There isn't enough room on the phone. */ | 1267 | /* There isn't enough room on the phone. */ |
1236 | /* TODO: Maybe in landscape only? */ | 1268 | /* TODO: Maybe in landscape only? */ |
1237 | return; | 1269 | return; |
1238 | } | 1270 | } |
1271 | iWindow *w = as_Window(d); | ||
1239 | iAssert(current_Root() == NULL); | 1272 | iAssert(current_Root() == NULL); |
1240 | if (d->splitMode != splitMode) { | 1273 | if (d->splitMode != splitMode) { |
1241 | int oldCount = numRoots_Window(d); | 1274 | int oldCount = numRoots_Window(w); |
1242 | setFreezeDraw_Window(d, iTrue); | 1275 | setFreezeDraw_Window(w, iTrue); |
1243 | if (oldCount == 2 && splitMode == 0) { | 1276 | if (oldCount == 2 && splitMode == 0) { |
1244 | /* Keep references to the tabs of the second root. */ | 1277 | /* Keep references to the tabs of the second root. */ |
1245 | const iDocumentWidget *curPage = document_Root(d->keyRoot); | 1278 | const iDocumentWidget *curPage = document_Root(w->keyRoot); |
1246 | if (!curPage) { | 1279 | if (!curPage) { |
1247 | /* All tabs closed on that side. */ | 1280 | /* All tabs closed on that side. */ |
1248 | curPage = document_Root(otherRoot_Window(d, d->keyRoot)); | 1281 | curPage = document_Root(otherRoot_Window(w, w->keyRoot)); |
1249 | } | 1282 | } |
1250 | iObjectList *tabs = listDocuments_App(d->roots[1]); | 1283 | iObjectList *tabs = listDocuments_App(w->roots[1]); |
1251 | iForEach(ObjectList, i, tabs) { | 1284 | iForEach(ObjectList, i, tabs) { |
1252 | setRoot_Widget(i.object, d->roots[0]); | 1285 | setRoot_Widget(i.object, w->roots[0]); |
1253 | } | 1286 | } |
1254 | setFocus_Widget(NULL); | 1287 | setFocus_Widget(NULL); |
1255 | delete_Root(d->roots[1]); | 1288 | delete_Root(w->roots[1]); |
1256 | d->roots[1] = NULL; | 1289 | w->roots[1] = NULL; |
1257 | d->keyRoot = d->roots[0]; | 1290 | w->keyRoot = w->roots[0]; |
1258 | /* Move the deleted root's tabs to the first root. */ | 1291 | /* Move the deleted root's tabs to the first root. */ |
1259 | setCurrent_Root(d->roots[0]); | 1292 | setCurrent_Root(w->roots[0]); |
1260 | iWidget *docTabs = findWidget_Root("doctabs"); | 1293 | iWidget *docTabs = findWidget_Root("doctabs"); |
1261 | iForEach(ObjectList, j, tabs) { | 1294 | iForEach(ObjectList, j, tabs) { |
1262 | appendTabPage_Widget(docTabs, j.object, "", 0, 0); | 1295 | appendTabPage_Widget(docTabs, j.object, "", 0, 0); |
@@ -1268,38 +1301,38 @@ void setSplitMode_Window(iWindow *d, int splitFlags) { | |||
1268 | } | 1301 | } |
1269 | else if (splitMode && oldCount == 1) { | 1302 | else if (splitMode && oldCount == 1) { |
1270 | /* Add a second root. */ | 1303 | /* Add a second root. */ |
1271 | iDocumentWidget *moved = document_Root(d->roots[0]); | 1304 | iDocumentWidget *moved = document_Root(w->roots[0]); |
1272 | iAssert(d->roots[1] == NULL); | 1305 | iAssert(w->roots[1] == NULL); |
1273 | const iBool addToLeft = (prefs_App()->pinSplit == 2); | 1306 | const iBool addToLeft = (prefs_App()->pinSplit == 2); |
1274 | size_t newRootIndex = 1; | 1307 | size_t newRootIndex = 1; |
1275 | if (addToLeft) { | 1308 | if (addToLeft) { |
1276 | iSwap(iRoot *, d->roots[0], d->roots[1]); | 1309 | iSwap(iRoot *, w->roots[0], w->roots[1]); |
1277 | newRootIndex = 0; | 1310 | newRootIndex = 0; |
1278 | } | 1311 | } |
1279 | d->roots[newRootIndex] = new_Root(); | 1312 | w->roots[newRootIndex] = new_Root(); |
1280 | d->keyRoot = d->roots[newRootIndex]; | 1313 | w->keyRoot = w->roots[newRootIndex]; |
1281 | setCurrent_Root(d->roots[newRootIndex]); | 1314 | setCurrent_Root(w->roots[newRootIndex]); |
1282 | createUserInterface_Root(d->roots[newRootIndex]); | 1315 | createUserInterface_Root(w->roots[newRootIndex]); |
1283 | if (!isEmpty_String(d->pendingSplitUrl)) { | 1316 | if (!isEmpty_String(d->pendingSplitUrl)) { |
1284 | postCommandf_Root(d->roots[newRootIndex], "open url:%s", | 1317 | postCommandf_Root(w->roots[newRootIndex], "open url:%s", |
1285 | cstr_String(d->pendingSplitUrl)); | 1318 | cstr_String(d->pendingSplitUrl)); |
1286 | clear_String(d->pendingSplitUrl); | 1319 | clear_String(d->pendingSplitUrl); |
1287 | } | 1320 | } |
1288 | else if (~splitFlags & noEvents_WindowSplit) { | 1321 | else if (~splitFlags & noEvents_WindowSplit) { |
1289 | iWidget *docTabs0 = findChild_Widget(d->roots[newRootIndex ^ 1]->widget, "doctabs"); | 1322 | iWidget *docTabs0 = findChild_Widget(w->roots[newRootIndex ^ 1]->widget, "doctabs"); |
1290 | iWidget *docTabs1 = findChild_Widget(d->roots[newRootIndex]->widget, "doctabs"); | 1323 | iWidget *docTabs1 = findChild_Widget(w->roots[newRootIndex]->widget, "doctabs"); |
1291 | /* If the old root has multiple tabs, move the current one to the new split. */ | 1324 | /* If the old root has multiple tabs, move the current one to the new split. */ |
1292 | if (tabCount_Widget(docTabs0) >= 2) { | 1325 | if (tabCount_Widget(docTabs0) >= 2) { |
1293 | int movedIndex = tabPageIndex_Widget(docTabs0, moved); | 1326 | int movedIndex = tabPageIndex_Widget(docTabs0, moved); |
1294 | removeTabPage_Widget(docTabs0, movedIndex); | 1327 | removeTabPage_Widget(docTabs0, movedIndex); |
1295 | showTabPage_Widget(docTabs0, tabPage_Widget(docTabs0, iMax(movedIndex - 1, 0))); | 1328 | showTabPage_Widget(docTabs0, tabPage_Widget(docTabs0, iMax(movedIndex - 1, 0))); |
1296 | iRelease(removeTabPage_Widget(docTabs1, 0)); /* delete the default tab */ | 1329 | iRelease(removeTabPage_Widget(docTabs1, 0)); /* delete the default tab */ |
1297 | setRoot_Widget(as_Widget(moved), d->roots[newRootIndex]); | 1330 | setRoot_Widget(as_Widget(moved), w->roots[newRootIndex]); |
1298 | prependTabPage_Widget(docTabs1, iClob(moved), "", 0, 0); | 1331 | prependTabPage_Widget(docTabs1, iClob(moved), "", 0, 0); |
1299 | postCommandf_App("tabs.switch page:%p", moved); | 1332 | postCommandf_App("tabs.switch page:%p", moved); |
1300 | } | 1333 | } |
1301 | else { | 1334 | else { |
1302 | postCommand_Root(d->roots[newRootIndex], "navigate.home"); | 1335 | postCommand_Root(w->roots[newRootIndex], "navigate.home"); |
1303 | } | 1336 | } |
1304 | } | 1337 | } |
1305 | setCurrent_Root(NULL); | 1338 | setCurrent_Root(NULL); |
@@ -1328,26 +1361,26 @@ void setSplitMode_Window(iWindow *d, int splitFlags) { | |||
1328 | } | 1361 | } |
1329 | #endif | 1362 | #endif |
1330 | if (~splitFlags & noEvents_WindowSplit) { | 1363 | if (~splitFlags & noEvents_WindowSplit) { |
1331 | updateSize_Window_(d, iTrue); | 1364 | updateSize_MainWindow_(d, iTrue); |
1332 | postCommand_App("window.unfreeze"); | 1365 | postCommand_App("window.unfreeze"); |
1333 | } | 1366 | } |
1334 | } | 1367 | } |
1335 | } | 1368 | } |
1336 | 1369 | ||
1337 | void setSnap_Window(iWindow *d, int snapMode) { | 1370 | void setSnap_MainWindow(iMainWindow *d, int snapMode) { |
1338 | if (!prefs_App()->customFrame) { | 1371 | if (!prefs_App()->customFrame) { |
1339 | if (snapMode == maximized_WindowSnap) { | 1372 | if (snapMode == maximized_WindowSnap) { |
1340 | SDL_MaximizeWindow(d->win); | 1373 | SDL_MaximizeWindow(d->base.win); |
1341 | } | 1374 | } |
1342 | else if (snapMode == fullscreen_WindowSnap) { | 1375 | else if (snapMode == fullscreen_WindowSnap) { |
1343 | SDL_SetWindowFullscreen(d->win, SDL_WINDOW_FULLSCREEN_DESKTOP); | 1376 | SDL_SetWindowFullscreen(d->base.win, SDL_WINDOW_FULLSCREEN_DESKTOP); |
1344 | } | 1377 | } |
1345 | else { | 1378 | else { |
1346 | if (snap_Window(d) == fullscreen_WindowSnap) { | 1379 | if (snap_MainWindow(d) == fullscreen_WindowSnap) { |
1347 | SDL_SetWindowFullscreen(d->win, 0); | 1380 | SDL_SetWindowFullscreen(d->base.win, 0); |
1348 | } | 1381 | } |
1349 | else { | 1382 | else { |
1350 | SDL_RestoreWindow(d->win); | 1383 | SDL_RestoreWindow(d->base.win); |
1351 | } | 1384 | } |
1352 | } | 1385 | } |
1353 | return; | 1386 | return; |
@@ -1359,9 +1392,9 @@ void setSnap_Window(iWindow *d, int snapMode) { | |||
1359 | const int snapDist = gap_UI * 4; | 1392 | const int snapDist = gap_UI * 4; |
1360 | iRect newRect = zero_Rect(); | 1393 | iRect newRect = zero_Rect(); |
1361 | SDL_Rect usable; | 1394 | SDL_Rect usable; |
1362 | SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->win), &usable); | 1395 | SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->base.win), &usable); |
1363 | if (d->place.snap == fullscreen_WindowSnap) { | 1396 | if (d->place.snap == fullscreen_WindowSnap) { |
1364 | SDL_SetWindowFullscreen(d->win, 0); | 1397 | SDL_SetWindowFullscreen(d->base.win, 0); |
1365 | } | 1398 | } |
1366 | d->place.snap = snapMode & ~redo_WindowSnap; | 1399 | d->place.snap = snapMode & ~redo_WindowSnap; |
1367 | switch (snapMode & mask_WindowSnap) { | 1400 | switch (snapMode & mask_WindowSnap) { |
@@ -1382,8 +1415,8 @@ void setSnap_Window(iWindow *d, int snapMode) { | |||
1382 | case yMaximized_WindowSnap: | 1415 | case yMaximized_WindowSnap: |
1383 | newRect.pos.y = 0; | 1416 | newRect.pos.y = 0; |
1384 | newRect.size.y = usable.h; | 1417 | newRect.size.y = usable.h; |
1385 | SDL_GetWindowSize(d->win, &newRect.size.x, NULL); | 1418 | SDL_GetWindowSize(d->base.win, &newRect.size.x, NULL); |
1386 | SDL_GetWindowPosition(d->win, &newRect.pos.x, NULL); | 1419 | SDL_GetWindowPosition(d->base.win, &newRect.pos.x, NULL); |
1387 | /* Snap the window to left/right edges, if close by. */ | 1420 | /* Snap the window to left/right edges, if close by. */ |
1388 | if (iAbs(right_Rect(newRect) - (usable.x + usable.w)) < snapDist) { | 1421 | if (iAbs(right_Rect(newRect) - (usable.x + usable.w)) < snapDist) { |
1389 | newRect.pos.x = usable.x + usable.w - width_Rect(newRect); | 1422 | newRect.pos.x = usable.x + usable.w - width_Rect(newRect); |
@@ -1393,7 +1426,7 @@ void setSnap_Window(iWindow *d, int snapMode) { | |||
1393 | } | 1426 | } |
1394 | break; | 1427 | break; |
1395 | case fullscreen_WindowSnap: | 1428 | case fullscreen_WindowSnap: |
1396 | SDL_SetWindowFullscreen(d->win, SDL_WINDOW_FULLSCREEN_DESKTOP); | 1429 | SDL_SetWindowFullscreen(d->base.win, SDL_WINDOW_FULLSCREEN_DESKTOP); |
1397 | break; | 1430 | break; |
1398 | } | 1431 | } |
1399 | if (snapMode & (topBit_WindowSnap | bottomBit_WindowSnap)) { | 1432 | if (snapMode & (topBit_WindowSnap | bottomBit_WindowSnap)) { |
@@ -1425,9 +1458,9 @@ void setSnap_Window(iWindow *d, int snapMode) { | |||
1425 | #endif /* defined (LAGRANGE_ENABLE_CUSTOM_FRAME) */ | 1458 | #endif /* defined (LAGRANGE_ENABLE_CUSTOM_FRAME) */ |
1426 | } | 1459 | } |
1427 | 1460 | ||
1428 | int snap_Window(const iWindow *d) { | 1461 | int snap_MainWindow(const iMainWindow *d) { |
1429 | if (!prefs_App()->customFrame) { | 1462 | if (!prefs_App()->customFrame) { |
1430 | const int flags = SDL_GetWindowFlags(d->win); | 1463 | const int flags = SDL_GetWindowFlags(d->base.win); |
1431 | if (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) { | 1464 | if (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) { |
1432 | return fullscreen_WindowSnap; | 1465 | return fullscreen_WindowSnap; |
1433 | } | 1466 | } |
diff --git a/src/ui/window.h b/src/ui/window.h index 282e1682..73e92391 100644 --- a/src/ui/window.h +++ b/src/ui/window.h | |||
@@ -29,8 +29,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
29 | #include <SDL_render.h> | 29 | #include <SDL_render.h> |
30 | #include <SDL_video.h> | 30 | #include <SDL_video.h> |
31 | 31 | ||
32 | iDeclareType(MainWindow) | ||
32 | iDeclareType(Window) | 33 | iDeclareType(Window) |
33 | iDeclareTypeConstructionArgs(Window, iRect rect) | 34 | iDeclareTypeConstructionArgs(MainWindow, iRect rect) |
35 | |||
36 | typedef iAny iAnyWindow; | ||
34 | 37 | ||
35 | enum iWindowSnap { | 38 | enum iWindowSnap { |
36 | none_WindowSnap = 0, | 39 | none_WindowSnap = 0, |
@@ -68,9 +71,14 @@ enum iWindowSplit { | |||
68 | noEvents_WindowSplit = iBit(11), | 71 | noEvents_WindowSplit = iBit(11), |
69 | }; | 72 | }; |
70 | 73 | ||
74 | enum iWindowType { | ||
75 | main_WindowType, | ||
76 | popup_WindowType, | ||
77 | }; | ||
78 | |||
71 | struct Impl_Window { | 79 | struct Impl_Window { |
80 | enum iWindowType type; | ||
72 | SDL_Window * win; | 81 | SDL_Window * win; |
73 | iWindowPlacement place; | ||
74 | iBool isDrawFrozen; /* avoids premature draws while restoring window state */ | 82 | iBool isDrawFrozen; /* avoids premature draws while restoring window state */ |
75 | iBool isExposed; | 83 | iBool isExposed; |
76 | iBool isMinimized; | 84 | iBool isMinimized; |
@@ -80,11 +88,6 @@ struct Impl_Window { | |||
80 | uint32_t focusGainedAt; | 88 | uint32_t focusGainedAt; |
81 | SDL_Renderer *render; | 89 | SDL_Renderer *render; |
82 | iInt2 size; | 90 | iInt2 size; |
83 | int splitMode; | ||
84 | int pendingSplitMode; | ||
85 | iString * pendingSplitUrl; /* URL to open in a newly opened split */ | ||
86 | iRoot * roots[2]; /* root widget and UI state; second one is for split mode */ | ||
87 | iRoot * keyRoot; /* root that has the current keyboard input focus */ | ||
88 | iWidget * hover; | 91 | iWidget * hover; |
89 | iWidget * lastHover; /* cleared if deleted */ | 92 | iWidget * lastHover; /* cleared if deleted */ |
90 | iWidget * mouseGrab; | 93 | iWidget * mouseGrab; |
@@ -94,56 +97,102 @@ struct Impl_Window { | |||
94 | float uiScale; | 97 | float uiScale; |
95 | uint32_t frameTime; | 98 | uint32_t frameTime; |
96 | double presentTime; | 99 | double presentTime; |
97 | SDL_Texture * appIcon; | ||
98 | SDL_Texture * borderShadow; | ||
99 | SDL_Cursor * cursors[SDL_NUM_SYSTEM_CURSORS]; | 100 | SDL_Cursor * cursors[SDL_NUM_SYSTEM_CURSORS]; |
100 | SDL_Cursor * pendingCursor; | 101 | SDL_Cursor * pendingCursor; |
101 | int loadAnimTimer; | 102 | iRoot * roots[2]; /* root widget and UI state; second one is for split mode */ |
102 | int keyboardHeight; /* mobile software keyboards */ | 103 | iRoot * keyRoot; /* root that has the current keyboard input focus */ |
104 | SDL_Texture * borderShadow; | ||
105 | }; | ||
106 | |||
107 | struct Impl_MainWindow { | ||
108 | iWindow base; | ||
109 | iWindowPlacement place; | ||
110 | int splitMode; | ||
111 | int pendingSplitMode; | ||
112 | iString * pendingSplitUrl; /* URL to open in a newly opened split */ | ||
113 | SDL_Texture * appIcon; | ||
114 | int keyboardHeight; /* mobile software keyboards */ | ||
103 | }; | 115 | }; |
104 | 116 | ||
105 | iBool processEvent_Window (iWindow *, const SDL_Event *); | 117 | iLocalDef enum iWindowType type_Window(const iAnyWindow *d) { |
118 | return ((const iWindow *) d)->type; | ||
119 | } | ||
120 | |||
121 | uint32_t id_Window (const iWindow *); | ||
122 | iInt2 size_Window (const iWindow *); | ||
123 | iInt2 maxTextureSize_Window (const iWindow *); | ||
124 | float uiScale_Window (const iWindow *); | ||
125 | iInt2 coord_Window (const iWindow *, int x, int y); | ||
126 | iInt2 mouseCoord_Window (const iWindow *, int whichDevice); | ||
127 | iAnyObject * hitChild_Window (const iWindow *, iInt2 coord); | ||
128 | uint32_t frameTime_Window (const iWindow *); | ||
129 | SDL_Renderer * renderer_Window (const iWindow *); | ||
130 | int numRoots_Window (const iWindow *); | ||
131 | iRoot * findRoot_Window (const iWindow *, const iWidget *widget); | ||
132 | iRoot * otherRoot_Window (const iWindow *, iRoot *root); | ||
133 | |||
106 | iBool dispatchEvent_Window (iWindow *, const SDL_Event *); | 134 | iBool dispatchEvent_Window (iWindow *, const SDL_Event *); |
107 | void invalidate_Window (iWindow *); /* discard all cached graphics */ | 135 | void invalidate_Window (iAnyWindow *); /* discard all cached graphics */ |
108 | void draw_Window (iWindow *); | 136 | void draw_Window (iWindow *); |
109 | void drawWhileResizing_Window(iWindow *d, int w, int h); /* workaround for SDL bug */ | ||
110 | void resize_Window (iWindow *, int w, int h); | ||
111 | void setTitle_Window (iWindow *, const iString *title); | ||
112 | void setUiScale_Window (iWindow *, float uiScale); | 137 | void setUiScale_Window (iWindow *, float uiScale); |
113 | void setFreezeDraw_Window (iWindow *, iBool freezeDraw); | 138 | void setFreezeDraw_Window (iWindow *, iBool freezeDraw); |
114 | iBool setKeyRoot_Window (iWindow *, iRoot *root); | ||
115 | void setCursor_Window (iWindow *, int cursor); | 139 | void setCursor_Window (iWindow *, int cursor); |
116 | void setSnap_Window (iWindow *, int snapMode); | 140 | iBool setKeyRoot_Window (iWindow *, iRoot *root); |
117 | void setKeyboardHeight_Window(iWindow *, int height); | ||
118 | void setSplitMode_Window (iWindow *, int splitMode); | ||
119 | void showToolbars_Window (iWindow *, iBool show); | ||
120 | iBool postContextClick_Window (iWindow *, const SDL_MouseButtonEvent *); | 141 | iBool postContextClick_Window (iWindow *, const SDL_MouseButtonEvent *); |
121 | void checkPendingSplit_Window(iWindow *); | ||
122 | void swapRoots_Window (iWindow *); | ||
123 | |||
124 | uint32_t id_Window (const iWindow *); | ||
125 | iInt2 size_Window (const iWindow *); | ||
126 | iInt2 maxTextureSize_Window (const iWindow *); | ||
127 | float uiScale_Window (const iWindow *); | ||
128 | iInt2 coord_Window (const iWindow *, int x, int y); | ||
129 | iInt2 mouseCoord_Window (const iWindow *, int whichDevice); | ||
130 | iAnyObject *hitChild_Window (const iWindow *, iInt2 coord); | ||
131 | uint32_t frameTime_Window (const iWindow *); | ||
132 | SDL_Renderer *renderer_Window (const iWindow *); | ||
133 | int snap_Window (const iWindow *); | ||
134 | iBool isFullscreen_Window (const iWindow *); | ||
135 | int numRoots_Window (const iWindow *); | ||
136 | iRoot * findRoot_Window (const iWindow *, const iWidget *widget); | ||
137 | iRoot * otherRoot_Window (const iWindow *, iRoot *root); | ||
138 | iWindow * get_Window (void); | ||
139 | 142 | ||
143 | iWindow * get_Window (void); | ||
140 | iBool isOpenGLRenderer_Window (void); | 144 | iBool isOpenGLRenderer_Window (void); |
141 | 145 | ||
142 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) | ||
143 | SDL_HitTestResult hitTest_Window(const iWindow *d, iInt2 pos); | ||
144 | #endif | ||
145 | |||
146 | iLocalDef iBool isExposed_Window(const iWindow *d) { | 146 | iLocalDef iBool isExposed_Window(const iWindow *d) { |
147 | iAssert(d); | 147 | iAssert(d); |
148 | return d->isExposed; | 148 | return d->isExposed; |
149 | } | 149 | } |
150 | |||
151 | iLocalDef iWindow *as_Window(iAnyWindow *d) { | ||
152 | iAssert(type_Window(d) == main_WindowType || type_Window(d) == popup_WindowType); | ||
153 | return (iWindow *) d; | ||
154 | } | ||
155 | |||
156 | iLocalDef const iWindow *constAs_Window(const iAnyWindow *d) { | ||
157 | iAssert(type_Window(d) == main_WindowType || type_Window(d) == popup_WindowType); | ||
158 | return (const iWindow *) d; | ||
159 | } | ||
160 | |||
161 | /*----------------------------------------------------------------------------------------------*/ | ||
162 | |||
163 | iLocalDef iWindow *asWindow_MainWindow(iMainWindow *d) { | ||
164 | iAssert(type_Window(d) == main_WindowType); | ||
165 | return &d->base; | ||
166 | } | ||
167 | |||
168 | void setTitle_MainWindow (iMainWindow *, const iString *title); | ||
169 | void setSnap_MainWindow (iMainWindow *, int snapMode); | ||
170 | void setKeyboardHeight_MainWindow (iMainWindow *, int height); | ||
171 | void setSplitMode_MainWindow (iMainWindow *, int splitMode); | ||
172 | void checkPendingSplit_MainWindow (iMainWindow *); | ||
173 | void swapRoots_MainWindow (iMainWindow *); | ||
174 | void showToolbars_MainWindow (iMainWindow *, iBool show); | ||
175 | void resize_MainWindow (iMainWindow *, int w, int h); | ||
176 | |||
177 | iBool processEvent_MainWindow (iMainWindow *, const SDL_Event *); | ||
178 | void draw_MainWindow (iMainWindow *); | ||
179 | void drawWhileResizing_MainWindow (iMainWindow *, int w, int h); /* workaround for SDL bug */ | ||
180 | |||
181 | int snap_MainWindow (const iMainWindow *); | ||
182 | iBool isFullscreen_Window (const iMainWindow *); | ||
183 | |||
184 | #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME) | ||
185 | SDL_HitTestResult hitTest_MainWindow(const iMainWindow *d, iInt2 pos); | ||
186 | #endif | ||
187 | |||
188 | iMainWindow * get_MainWindow (void); | ||
189 | |||
190 | iLocalDef iMainWindow *as_MainWindow(iAnyWindow *d) { | ||
191 | iAssert(type_Window(d) == main_WindowType); | ||
192 | return (iMainWindow *) d; | ||
193 | } | ||
194 | |||
195 | iLocalDef const iMainWindow *constAs_MainWindow(const iAnyWindow *d) { | ||
196 | iAssert(type_Window(d) == main_WindowType); | ||
197 | return (const iMainWindow *) d; | ||
198 | } | ||