=> 81007a2debffebc97c230cd810fb1bf10760180f
[1mdiff --git a/src/app.c b/src/app.c[m [1mindex e06a32ce..91b3a06d 100644[m [1m--- a/src/app.c[m [1m+++ b/src/app.c[m [36m@@ -117,7 +117,7 @@[m [mstruct Impl_App {[m iGmCerts * certs;[m iVisited * visited;[m iBookmarks * bookmarks;[m [31m- iWindow * window;[m [32m+[m[32m iMainWindow *window;[m iSortedArray tickers; /* per-frame callbacks, used for animations */[m uint32_t lastTickerTime;[m uint32_t elapsedSinceLastTicker;[m [36m@@ -188,7 +188,7 @@[m [mstatic iString *serializePrefs_App_(const iApp *d) {[m /* On macOS, maximization should be applied at creation time or the window will take[m a moment to animate to its maximized size. */[m #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME)[m [31m- if (snap_Window(d->window)) {[m [32m+[m[32m if (snap_MainWindow(d->window)) {[m if (~SDL_GetWindowFlags(d->window->win) & SDL_WINDOW_MINIMIZED) {[m /* Save the actual visible window position, too, because snapped windows may[m still be resized/moved without affecting normalRect. */[m [36m@@ -196,17 +196,17 @@[m [mstatic iString *serializePrefs_App_(const iApp *d) {[m SDL_GetWindowSize(d->window->win, &w, &h);[m appendFormat_String([m str, "~window.setrect snap:%d width:%d height:%d coord:%d %d\n",[m [31m- snap_Window(d->window), w, h, x, y);[m [32m+[m[32m snap_MainWindow(d->window), w, h, x, y);[m }[m }[m #elif !defined (iPlatformApple)[m [31m- if (snap_Window(d->window) == maximized_WindowSnap) {[m [32m+[m[32m if (snap_MainWindow(d->window) == maximized_WindowSnap) {[m appendFormat_String(str, "~window.maximize\n");[m }[m #endif[m }[m appendFormat_String(str, "uilang id:%s\n", cstr_String(&d->prefs.uiLanguage));[m [31m- appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(d->window));[m [32m+[m[32m appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(as_Window(d->window)));[m appendFormat_String(str, "prefs.dialogtab arg:%d\n", d->prefs.dialogTab);[m appendFormat_String(str, "font.set arg:%d\n", d->prefs.font);[m appendFormat_String(str, "font.user path:%s\n", cstr_String(&d->prefs.symbolFontPath));[m [36m@@ -414,8 +414,8 @@[m [mstatic iBool loadState_App_(iApp *d) {[m const int splitMode = read32_File(f);[m const int keyRoot = read32_File(f);[m d->window->pendingSplitMode = splitMode;[m [31m- setSplitMode_Window(d->window, splitMode | noEvents_WindowSplit);[m [31m- d->window->keyRoot = d->window->roots[keyRoot];[m [32m+[m[32m setSplitMode_MainWindow(d->window, splitMode | noEvents_WindowSplit);[m [32m+[m[32m d->window->base.keyRoot = d->window->base.roots[keyRoot];[m }[m else if (!memcmp(magic, magicSidebar_App_, 4)) {[m const uint16_t bits = readU16_File(f);[m [36m@@ -426,7 +426,7 @@[m [mstatic iBool loadState_App_(iApp *d) {[m };[m const uint8_t rootIndex = bits & 0xff;[m const uint8_t flags = bits >> 8;[m [31m- iRoot *root = d->window->roots[rootIndex];[m [32m+[m[32m iRoot *root = d->window->base.roots[rootIndex];[m if (root) {[m iSidebarWidget *sidebar = findChild_Widget(root->widget, "sidebar");[m iSidebarWidget *sidebar2 = findChild_Widget(root->widget, "sidebar2");[m [36m@@ -443,10 +443,10 @@[m [mstatic iBool loadState_App_(iApp *d) {[m else if (!memcmp(magic, magicTabDocument_App_, 4)) {[m const int8_t flags = read8_File(f);[m int rootIndex = flags & rootIndex1_DocumentStateFlag ? 1 : 0;[m [31m- if (rootIndex > numRoots_Window(d->window) - 1) {[m [32m+[m[32m if (rootIndex > numRoots_Window(as_Window(d->window)) - 1) {[m rootIndex = 0;[m }[m [31m- setCurrent_Root(d->window->roots[rootIndex]);[m [32m+[m[32m setCurrent_Root(d->window->base.roots[rootIndex]);[m if (isFirstTab[rootIndex]) {[m isFirstTab[rootIndex] = iFalse;[m /* There is one pre-created tab in each root. */[m [36m@@ -469,7 +469,7 @@[m [mstatic iBool loadState_App_(iApp *d) {[m }[m if (d->window->splitMode) {[m /* Update root placement. */[m [31m- resize_Window(d->window, -1, -1);[m [32m+[m[32m resize_MainWindow(d->window, -1, -1);[m }[m iForIndices(i, current) {[m postCommandf_Root(NULL, "tabs.switch page:%p", current[i]);[m [36m@@ -483,7 +483,7 @@[m [mstatic iBool loadState_App_(iApp *d) {[m static void saveState_App_(const iApp *d) {[m iUnused(d);[m trimCache_App();[m [31m- iWindow *win = d->window;[m [32m+[m[32m iMainWindow *win = d->window;[m /* UI state is saved in binary because it is quite complex (e.g.,[m navigation history, cached content) and depends closely on the widget[m tree. The data is largely not reorderable and should not be modified[m [36m@@ -495,11 +495,11 @@[m [mstatic void saveState_App_(const iApp *d) {[m /* Begin with window state. */ {[m writeData_File(f, magicWindow_App_, 4);[m writeU32_File(f, win->splitMode);[m [31m- writeU32_File(f, win->keyRoot == win->roots[0] ? 0 : 1);[m [32m+[m[32m writeU32_File(f, win->base.keyRoot == win->base.roots[0] ? 0 : 1);[m }[m /* State of UI elements. */ {[m [31m- iForIndices(i, win->roots) {[m [31m- const iRoot *root = win->roots[i];[m [32m+[m[32m iForIndices(i, win->base.roots) {[m [32m+[m[32m const iRoot *root = win->base.roots[i];[m if (root) {[m writeData_File(f, magicSidebar_App_, 4);[m const iSidebarWidget *sidebar = findChild_Widget(root->widget, "sidebar");[m [36m@@ -520,7 +520,7 @@[m [mstatic void saveState_App_(const iApp *d) {[m const iWidget *widget = constAs_Widget(i.object);[m writeData_File(f, magicTabDocument_App_, 4);[m int8_t flags = (document_Root(widget->root) == i.object ? current_DocumentStateFlag : 0);[m [31m- if (widget->root == win->roots[1]) {[m [32m+[m[32m if (widget->root == win->base.roots[1]) {[m flags |= rootIndex1_DocumentStateFlag;[m }[m write8_File(f, flags);[m [36m@@ -801,7 +801,7 @@[m [mstatic void init_App_(iApp *d, int argc, char **argv) {[m d->initialWindowRect.size.y = toInt_String(value_CommandLineArg(arg, 0));[m }[m }[m [31m- d->window = new_Window(d->initialWindowRect);[m [32m+[m[32m d->window = new_MainWindow(d->initialWindowRect);[m load_Visited(d->visited, dataDir_App_());[m load_Bookmarks(d->bookmarks, dataDir_App_());[m load_MimeHooks(d->mimehooks, dataDir_App_());[m [36m@@ -848,7 +848,7 @@[m [mstatic void init_App_(iApp *d, int argc, char **argv) {[m fetchRemote_Bookmarks(d->bookmarks);[m if (deviceType_App() != desktop_AppDeviceType) {[m /* HACK: Force a resize so widgets update their state. */[m [31m- resize_Window(d->window, -1, -1);[m [32m+[m[32m resize_MainWindow(d->window, -1, -1);[m }[m }[m [m [36m@@ -871,7 +871,7 @@[m [mstatic void deinit_App(iApp *d) {[m delete_GmCerts(d->certs);[m save_MimeHooks(d->mimehooks);[m delete_MimeHooks(d->mimehooks);[m [31m- delete_Window(d->window);[m [32m+[m[32m delete_MainWindow(d->window);[m d->window = NULL;[m deinit_CommandLine(&d->args);[m iRelease(d->launchCommands);[m [36m@@ -1110,7 +1110,7 @@[m [mvoid processEvents_App(enum iAppEventMode eventMode) {[m clearCache_App_();[m break;[m case SDL_APP_WILLENTERFOREGROUND:[m [31m- invalidate_Window(d->window);[m [32m+[m[32m invalidate_Window(as_Window(d->window));[m break;[m case SDL_APP_DIDENTERFOREGROUND:[m gotEvents = iTrue;[m [36m@@ -1125,17 +1125,17 @@[m [mvoid processEvents_App(enum iAppEventMode eventMode) {[m #if defined (iPlatformAppleMobile)[m updateNowPlayingInfo_iOS();[m #endif[m [31m- setFreezeDraw_Window(d->window, iTrue);[m [32m+[m[32m setFreezeDraw_Window(as_Window(d), iTrue);[m savePrefs_App_(d);[m saveState_App_(d);[m break;[m case SDL_APP_TERMINATING:[m [31m- setFreezeDraw_Window(d->window, iTrue);[m [32m+[m[32m setFreezeDraw_Window(as_Window(d), iTrue);[m savePrefs_App_(d);[m saveState_App_(d);[m break;[m case SDL_DROPFILE: {[m [31m- iBool wasUsed = processEvent_Window(d->window, &ev);[m [32m+[m[32m iBool wasUsed = processEvent_MainWindow(d->window, &ev);[m if (!wasUsed) {[m iBool newTab = iFalse;[m if (elapsedSeconds_Time(&d->lastDropTime) < 0.1) {[m [36m@@ -1177,10 +1177,10 @@[m [mvoid processEvents_App(enum iAppEventMode eventMode) {[m #endif[m if (ev.type == SDL_USEREVENT && ev.user.code == arrange_UserEventCode) {[m printf("[App] rearrange\n");[m [31m- resize_Window(d->window, -1, -1);[m [31m- iForIndices(i, d->window->roots) {[m [31m- if (d->window->roots[i]) {[m [31m- d->window->roots[i]->pendingArrange = iFalse;[m [32m+[m[32m resize_MainWindow(d->window, -1, -1);[m [32m+[m[32m iForIndices(i, d->window->base.roots) {[m [32m+[m[32m if (d->window->base.roots[i]) {[m [32m+[m[32m d->window->base.roots[i]->pendingArrange = iFalse;[m }[m }[m // if (ev.user.data2 == d->window->roots[0]) {[m [36m@@ -1209,8 +1209,8 @@[m [mvoid processEvents_App(enum iAppEventMode eventMode) {[m if (ev.wheel.which == 0) {[m /* Trackpad with precise scrolling w/inertia (points). */[m setPerPixel_MouseWheelEvent(&ev.wheel, iTrue);[m [31m- ev.wheel.x *= -d->window->pixelRatio;[m [31m- ev.wheel.y *= d->window->pixelRatio;[m [32m+[m[32m ev.wheel.x *= -d->window->base.pixelRatio;[m [32m+[m[32m ev.wheel.y *= d->window->base.pixelRatio;[m /* Only scroll on one axis at a time. */[m if (iAbs(ev.wheel.x) > iAbs(ev.wheel.y)) {[m ev.wheel.y = 0;[m [36m@@ -1268,8 +1268,8 @@[m [mvoid processEvents_App(enum iAppEventMode eventMode) {[m }[m }[m #endif[m [31m- d->window->lastHover = d->window->hover;[m [31m- iBool wasUsed = processEvent_Window(d->window, &ev);[m [32m+[m[32m d->window->base.lastHover = d->window->base.hover;[m [32m+[m[32m iBool wasUsed = processEvent_MainWindow(d->window, &ev);[m if (!wasUsed) {[m /* There may be a key bindings for this. */[m wasUsed = processEvent_Keys(&ev);[m [36m@@ -1289,8 +1289,8 @@[m [mvoid processEvents_App(enum iAppEventMode eventMode) {[m handleCommand_MacOS(command_UserEvent(&ev));[m #endif[m if (isMetricsChange_UserEvent(&ev)) {[m [31m- iForIndices(i, d->window->roots) {[m [31m- iRoot *root = d->window->roots[i];[m [32m+[m[32m iForIndices(i, d->window->base.roots) {[m [32m+[m[32m iRoot *root = d->window->base.roots[i];[m if (root) {[m arrange_Widget(root->widget);[m }[m [36m@@ -1304,9 +1304,9 @@[m [mvoid processEvents_App(enum iAppEventMode eventMode) {[m free(ev.user.data1);[m }[m /* Update when hover has changed. */[m [31m- if (d->window->lastHover != d->window->hover) {[m [31m- refresh_Widget(d->window->lastHover);[m [31m- refresh_Widget(d->window->hover);[m [32m+[m[32m if (d->window->base.lastHover != d->window->base.hover) {[m [32m+[m[32m refresh_Widget(d->window->base.lastHover);[m [32m+[m[32m refresh_Widget(d->window->base.hover);[m }[m break;[m }[m [36m@@ -1362,15 +1362,16 @@[m [mstatic int resizeWatcher_(void *user, SDL_Event *event) {[m dispatchEvent_Window(d->window, &u);[m }[m #endif[m [31m- drawWhileResizing_Window(d->window, winev->data1, winev->data2);[m [32m+[m[32m drawWhileResizing_MainWindow(d->window, winev->data1, winev->data2);[m }[m return 0;[m }[m [m static int run_App_(iApp *d) {[m [31m- iForIndices(i, d->window->roots) {[m [31m- if (d->window->roots[i]) {[m [31m- arrange_Widget(d->window->roots[i]->widget);[m [32m+[m[32m /* Initial arrangement. */[m [32m+[m[32m iForIndices(i, d->window->base.roots) {[m [32m+[m[32m if (d->window->base.roots[i]) {[m [32m+[m[32m arrange_Widget(d->window->base.roots[i]->widget);[m }[m }[m d->isRunning = iTrue;[m [36m@@ -1384,7 +1385,7 @@[m [mstatic int run_App_(iApp *d) {[m runTickers_App_(d);[m refresh_App();[m /* Change the widget tree while we are not iterating through it. */[m [31m- checkPendingSplit_Window(d->window);[m [32m+[m[32m checkPendingSplit_MainWindow(d->window);[m recycle_Garbage();[m }[m SDL_DelEventWatch(resizeWatcher_, d);[m [36m@@ -1393,8 +1394,8 @@[m [mstatic int run_App_(iApp *d) {[m [m void refresh_App(void) {[m iApp *d = &app_;[m [31m- iForIndices(i, d->window->roots) {[m [31m- iRoot *root = d->window->roots[i];[m [32m+[m[32m iForIndices(i, d->window->base.roots) {[m [32m+[m[32m iRoot *root = d->window->base.roots[i];[m if (root) {[m destroyPending_Root(root);[m }[m [36m@@ -1409,7 +1410,7 @@[m [mvoid refresh_App(void) {[m }[m // iTime draw;[m // initCurrent_Time(&draw);[m [31m- draw_Window(d->window);[m [32m+[m[32m draw_MainWindow(d->window);[m // printf("draw: %lld \u03bcs\n", (long long) (elapsedSeconds_Time(&draw) * 1000000));[m // fflush(stdout);[m if (d->warmupFrames > 0) {[m [36m@@ -1545,7 +1546,7 @@[m [mvoid postCommandf_App(const char *command, ...) {[m }[m [m void rootOrder_App(iRoot *roots[2]) {[m [31m- const iWindow *win = app_.window;[m [32m+[m[32m const iWindow *win = as_Window(app_.window);[m roots[0] = win->keyRoot;[m roots[1] = (roots[0] == win->roots[0] ? win->roots[1] : win->roots[0]);[m }[m [36m@@ -1979,7 +1980,7 @@[m [mconst iString *searchQueryUrl_App(const iString *queryStringUnescaped) {[m [m iBool handleCommand_App(const char *cmd) {[m iApp *d = &app_;[m [31m- const iBool isFrozen = !d->window || d->window->isDrawFrozen;[m [32m+[m[32m const iBool isFrozen = !d->window || d->window->base.isDrawFrozen;[m if (equal_Command(cmd, "config.error")) {[m makeSimpleMessage_Widget(uiTextCaution_ColorEscape "CONFIG ERROR",[m format_CStr("Error in config file: %s\n"[m [36m@@ -2011,13 +2012,13 @@[m [miBool handleCommand_App(const char *cmd) {[m }[m else if (equal_Command(cmd, "ui.split")) {[m if (argLabel_Command(cmd, "swap")) {[m [31m- swapRoots_Window(d->window);[m [32m+[m[32m swapRoots_MainWindow(d->window);[m return iTrue;[m }[m d->window->pendingSplitMode =[m (argLabel_Command(cmd, "axis") ? vertical_WindowSplit : 0) | (arg_Command(cmd) << 1);[m const char *url = suffixPtr_Command(cmd, "url");[m [31m- setCStr_String(get_Window()->pendingSplitUrl, url ? url : "");[m [32m+[m[32m setCStr_String(d->window->pendingSplitUrl, url ? url : "");[m postRefresh_App();[m return iTrue;[m }[m [36m@@ -2031,17 +2032,17 @@[m [miBool handleCommand_App(const char *cmd) {[m }[m else if (equal_Command(cmd, "window.maximize")) {[m if (!argLabel_Command(cmd, "toggle")) {[m [31m- setSnap_Window(d->window, maximized_WindowSnap);[m [32m+[m[32m setSnap_MainWindow(d->window, maximized_WindowSnap);[m }[m else {[m [31m- setSnap_Window(d->window, snap_Window(d->window) == maximized_WindowSnap ? 0 :[m [32m+[m[32m setSnap_MainWindow(d->window, snap_MainWindow(d->window) == maximized_WindowSnap ? 0 :[m maximized_WindowSnap);[m }[m return iTrue;[m }[m else if (equal_Command(cmd, "window.fullscreen")) {[m [31m- const iBool wasFull = snap_Window(d->window) == fullscreen_WindowSnap;[m [31m- setSnap_Window(d->window, wasFull ? 0 : fullscreen_WindowSnap);[m [32m+[m[32m const iBool wasFull = snap_MainWindow(d->window) == fullscreen_WindowSnap;[m [32m+[m[32m setSnap_MainWindow(d->window, wasFull ? 0 : fullscreen_WindowSnap);[m postCommandf_App("window.fullscreen.changed arg:%d", !wasFull);[m return iTrue;[m }[m [36m@@ -2210,7 +2211,7 @@[m [miBool handleCommand_App(const char *cmd) {[m equal_Command(cmd, "prefs.mono.gopher.changed")) {[m const iBool isSet = (arg_Command(cmd) != 0);[m if (!isFrozen) {[m [31m- setFreezeDraw_Window(d->window, iTrue);[m [32m+[m[32m setFreezeDraw_Window(as_Window(d->window), iTrue);[m }[m if (startsWith_CStr(cmd, "prefs.mono.gemini")) {[m d->prefs.monospaceGemini = isSet;[m [36m@@ -2405,8 +2406,8 @@[m [miBool handleCommand_App(const char *cmd) {[m iRoot *root = get_Root();[m iRoot *oldRoot = root;[m if (newTab & otherRoot_OpenTabFlag) {[m [31m- root = otherRoot_Window(d->window, root);[m [31m- setKeyRoot_Window(d->window, root);[m [32m+[m[32m root = otherRoot_Window(as_Window(d->window), root);[m [32m+[m[32m setKeyRoot_Window(as_Window(d->window), root);[m setCurrent_Root(root); /* need to change for widget creation */[m }[m iDocumentWidget *doc = document_Command(cmd);[m [36m@@ -2560,7 +2561,8 @@[m [miBool handleCommand_App(const char *cmd) {[m return iTrue;[m }[m else if (equal_Command(cmd, "keyroot.next")) {[m [31m- if (setKeyRoot_Window(d->window, otherRoot_Window(d->window, d->window->keyRoot))) {[m [32m+[m[32m if (setKeyRoot_Window(as_Window(d->window),[m [32m+[m[32m otherRoot_Window(as_Window(d->window), d->window->base.keyRoot))) {[m setFocus_Widget(NULL);[m }[m return iTrue;[m [36m@@ -2592,7 +2594,7 @@[m [miBool handleCommand_App(const char *cmd) {[m format_CStr("returnkey.set arg:%d", d->prefs.returnKey));[m setToggle_Widget(findChild_Widget(dlg, "prefs.retainwindow"), d->prefs.retainWindowSize);[m setText_InputWidget(findChild_Widget(dlg, "prefs.uiscale"),[m [31m- collectNewFormat_String("%g", uiScale_Window(d->window)));[m [32m+[m[32m collectNewFormat_String("%g", uiScale_Window(as_Window(d->window))));[m setFlags_Widget(findChild_Widget(dlg, format_CStr("prefs.font.%d", d->prefs.font)),[m selected_WidgetFlag,[m iTrue);[m [36m@@ -2749,7 +2751,7 @@[m [miBool handleCommand_App(const char *cmd) {[m /* Set of open tabs has changed. */[m postCommand_App("document.openurls.changed");[m if (deviceType_App() == phone_AppDeviceType) {[m [31m- showToolbar_Root(d->window->roots[0], iTrue);[m [32m+[m[32m showToolbar_Root(d->window->base.roots[0], iTrue);[m }[m return iFalse;[m }[m [36m@@ -2825,8 +2827,8 @@[m [miBool handleCommand_App(const char *cmd) {[m }[m else if (equal_Command(cmd, "ipc.signal")) {[m if (argLabel_Command(cmd, "raise")) {[m [31m- if (d->window && d->window->win) {[m [31m- SDL_RaiseWindow(d->window->win);[m [32m+[m[32m if (d->window && d->window->base.win) {[m [32m+[m[32m SDL_RaiseWindow(d->window->base.win);[m }[m }[m signal_Ipc(arg_Command(cmd));[m [1mdiff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c[m [1mindex 8ea695d5..ed9e41d6 100644[m [1m--- a/src/ui/documentwidget.c[m [1m+++ b/src/ui/documentwidget.c[m [36m@@ -934,7 +934,7 @@[m [mstatic void updateWindowTitle_DocumentWidget_(const iDocumentWidget *d) {[m iString *text = collect_String(joinCStr_StringArray(title, " \u2014 "));[m if (setWindow) {[m /* Longest version for the window title, and omit the icon. */[m [31m- setTitle_Window(get_Window(), text);[m [32m+[m[32m setTitle_MainWindow(get_MainWindow(), text);[m setWindow = iFalse;[m }[m const iChar siteIcon = siteIcon_GmDocument(d->doc);[m [1mdiff --git a/src/ui/paint.c b/src/ui/paint.c[m [1mindex a3ee32c6..5506f845 100644[m [1m--- a/src/ui/paint.c[m [1m+++ b/src/ui/paint.c[m [36m@@ -152,6 +152,9 @@[m [mvoid drawSoftShadow_Paint(const iPaint *d, iRect inner, int thickness, int color[m addv_I2(&inner.pos, origin_Paint);[m SDL_Renderer *render = renderer_Paint_(d);[m SDL_Texture *shadow = get_Window()->borderShadow;[m [32m+[m[32m if (!shadow) {[m [32m+[m[32m return;[m [32m+[m[32m }[m const iInt2 size = size_SDLTexture(shadow);[m const iRect outer = expanded_Rect(inner, init1_I2(thickness));[m const iColor clr = get_Color(color);[m [1mdiff --git a/src/ui/root.c b/src/ui/root.c[m [1mindex 6ea5f521..52a08eca 100644[m [1m--- a/src/ui/root.c[m [1m+++ b/src/ui/root.c[m [36m@@ -383,18 +383,18 @@[m [mstatic iBool handleRootCommands_(iWidget *root, const char *cmd) {[m else if (equal_Command(cmd, "window.setrect")) {[m const int snap = argLabel_Command(cmd, "snap");[m if (snap) {[m [31m- iWindow *window = get_Window();[m [32m+[m[32m iMainWindow *window = get_MainWindow();[m iInt2 coord = coord_Command(cmd);[m iInt2 size = init_I2(argLabel_Command(cmd, "width"),[m argLabel_Command(cmd, "height"));[m [31m- SDL_SetWindowPosition(window->win, coord.x, coord.y);[m [31m- SDL_SetWindowSize(window->win, size.x, size.y);[m [32m+[m[32m SDL_SetWindowPosition(window->base.win, coord.x, coord.y);[m [32m+[m[32m SDL_SetWindowSize(window->base.win, size.x, size.y);[m window->place.snap = snap;[m return iTrue;[m }[m }[m else if (equal_Command(cmd, "window.restore")) {[m [31m- setSnap_Window(get_Window(), none_WindowSnap);[m [32m+[m[32m setSnap_MainWindow(get_MainWindow(), none_WindowSnap);[m return iTrue;[m }[m else if (equal_Command(cmd, "window.minimize")) {[m [36m@@ -1525,5 +1525,5 @@[m [miRect safeRect_Root(const iRoot *d) {[m }[m [m iInt2 visibleSize_Root(const iRoot *d) {[m [31m- return addY_I2(size_Root(d), -get_Window()->keyboardHeight);[m [32m+[m[32m return addY_I2(size_Root(d), -get_MainWindow()->keyboardHeight);[m }[m [1mdiff --git a/src/ui/uploadwidget.c b/src/ui/uploadwidget.c[m [1mindex 72608851..ba7545fd 100644[m [1m--- a/src/ui/uploadwidget.c[m [1m+++ b/src/ui/uploadwidget.c[m [36m@@ -97,7 +97,7 @@[m [mstatic void updateInputMaxHeight_UploadWidget_(iUploadWidget *d) {[m height_Widget(findChild_Widget(w, "dialogbuttons")) +[m 12 * gap_UI);[m const int avail = bottom_Rect(safeRect_Root(w->root)) - footerHeight -[m [31m- get_Window()->keyboardHeight;[m [32m+[m[32m get_MainWindow()->keyboardHeight;[m setLineLimits_InputWidget(d->input,[m minLines_InputWidget(d->input),[m iMaxi(minLines_InputWidget(d->input),[m [1mdiff --git a/src/ui/util.c b/src/ui/util.c[m [1mindex 01939e66..721aed2d 100644[m [1m--- a/src/ui/util.c[m [1m+++ b/src/ui/util.c[m [36m@@ -1222,7 +1222,7 @@[m [mstatic void updateValueInputWidth_(iWidget *dlg) {[m iMin(rootSize.x, iMaxi(iMaxi(100 * gap_UI, title->rect.size.x), prompt->rect.size.x));[m }[m /* Adjust the maximum number of visible lines. */[m [31m- int footer = 6 * gap_UI + get_Window()->keyboardHeight;[m [32m+[m[32m int footer = 6 * gap_UI + get_MainWindow()->keyboardHeight;[m iWidget *buttons = findChild_Widget(dlg, "dialogbuttons");[m if (buttons) {[m footer += height_Widget(buttons);[m [1mdiff --git a/src/ui/widget.c b/src/ui/widget.c[m [1mindex c1fb9e95..23c19315 100644[m [1m--- a/src/ui/widget.c[m [1m+++ b/src/ui/widget.c[m [36m@@ -1088,7 +1088,7 @@[m [mvoid scrollInfo_Widget(const iWidget *d, iWidgetScrollInfo *info) {[m iRect bounds = boundsWithoutVisualOffset_Widget(d);[m const iRect winRect = adjusted_Rect(safeRect_Root(d->root),[m zero_I2(),[m [31m- init_I2(0, -get_Window()->keyboardHeight));[m [32m+[m[32m init_I2(0, -get_MainWindow()->keyboardHeight));[m info->height = bounds.size.y;[m info->avail = height_Rect(winRect);[m if (info->avail >= info->height) {[m [36m@@ -1109,7 +1109,7 @@[m [miBool scrollOverflow_Widget(iWidget *d, int delta) {[m iRect bounds = boundsWithoutVisualOffset_Widget(d);[m const iRect winRect = adjusted_Rect(safeRect_Root(d->root),[m zero_I2(),[m [31m- init_I2(0, -get_Window()->keyboardHeight));[m [32m+[m[32m init_I2(0, -get_MainWindow()->keyboardHeight));[m const int yTop = top_Rect(winRect);[m const int yBottom = bottom_Rect(winRect);[m if (top_Rect(bounds) >= yTop && bottom_Rect(bounds) < yBottom) {[m [1mdiff --git a/src/ui/window.c b/src/ui/window.c[m [1mindex b8198636..92125d81 100644[m [1m--- a/src/ui/window.c[m [1m+++ b/src/ui/window.c[m [36m@@ -67,7 +67,7 @@[m [mstatic float initialUiScale_ = 1.1f;[m [m static iBool isOpenGLRenderer_;[m [m [31m-iDefineTypeConstructionArgs(Window, (iRect rect), rect)[m [32m+[m[32miDefineTypeConstructionArgs(MainWindow, (iRect rect), rect)[m [m /* TODO: Define menus per platform. */[m [m [36m@@ -169,17 +169,17 @@[m [mint numRoots_Window(const iWindow *d) {[m return num;[m }[m [m [31m-static void windowSizeChanged_Window_(iWindow *d) {[m [31m- const int numRoots = numRoots_Window(d);[m [31m- const iInt2 rootSize = d->size;[m [32m+[m[32mstatic void windowSizeChanged_MainWindow_(iMainWindow *d) {[m [32m+[m[32m const int numRoots = numRoots_Window(as_Window(d));[m [32m+[m[32m const iInt2 rootSize = d->base.size;[m const int weights[2] = {[m [31m- d->roots[0] ? (d->splitMode & twoToOne_WindowSplit ? 2 : 1) : 0,[m [31m- d->roots[1] ? (d->splitMode & oneToTwo_WindowSplit ? 2 : 1) : 0,[m [32m+[m[32m d->base.roots[0] ? (d->splitMode & twoToOne_WindowSplit ? 2 : 1) : 0,[m [32m+[m[32m d->base.roots[1] ? (d->splitMode & oneToTwo_WindowSplit ? 2 : 1) : 0,[m };[m const int totalWeight = weights[0] + weights[1];[m int w = 0;[m [31m- iForIndices(i, d->roots) {[m [31m- iRoot *root = d->roots[i];[m [32m+[m[32m iForIndices(i, d->base.roots) {[m [32m+[m[32m iRoot *root = d->base.roots[i];[m if (root) {[m iRect *rect = &root->widget->rect;[m /* Horizontal split frame. */[m [36m@@ -199,26 +199,26 @@[m [mstatic void windowSizeChanged_Window_(iWindow *d) {[m }[m }[m [m [31m-static void setupUserInterface_Window(iWindow *d) {[m [32m+[m[32mstatic void setupUserInterface_MainWindow(iMainWindow *d) {[m #if defined (iHaveNativeMenus)[m insertMacMenus_();[m #endif[m /* One root is created by default. */[m [31m- d->roots[0] = new_Root();[m [31m- setCurrent_Root(d->roots[0]);[m [31m- createUserInterface_Root(d->roots[0]);[m [32m+[m[32m d->base.roots[0] = new_Root();[m [32m+[m[32m setCurrent_Root(d->base.roots[0]);[m [32m+[m[32m createUserInterface_Root(d->base.roots[0]);[m setCurrent_Root(NULL);[m /* One of the roots always has keyboard input focus. */[m [31m- d->keyRoot = d->roots[0];[m [32m+[m[32m d->base.keyRoot = d->base.roots[0];[m }[m [m [31m-static void updateSize_Window_(iWindow *d, iBool notifyAlways) {[m [31m- iInt2 *size = &d->size;[m [32m+[m[32mstatic void updateSize_MainWindow_(iMainWindow *d, iBool notifyAlways) {[m [32m+[m[32m iInt2 *size = &d->base.size;[m const iInt2 oldSize = *size;[m [31m- SDL_GetRendererOutputSize(d->render, &size->x, &size->y);[m [32m+[m[32m SDL_GetRendererOutputSize(d->base.render, &size->x, &size->y);[m size->y -= d->keyboardHeight;[m if (notifyAlways || !isEqual_I2(oldSize, *size)) {[m [31m- windowSizeChanged_Window_(d);[m [32m+[m[32m windowSizeChanged_MainWindow_(d);[m if (!isEqual_I2(*size, d->place.lastNotifiedSize)) {[m const iBool isHoriz = (d->place.lastNotifiedSize.x != size->x);[m const iBool isVert = (d->place.lastNotifiedSize.y != size->y);[m [36m@@ -234,8 +234,8 @@[m [mstatic void updateSize_Window_(iWindow *d, iBool notifyAlways) {[m }[m }[m [m [31m-void drawWhileResizing_Window(iWindow *d, int w, int h) {[m [31m- draw_Window(d); [m [32m+[m[32mvoid drawWhileResizing_MainWindow(iMainWindow *d, int w, int h) {[m [32m+[m[32m draw_MainWindow(d);[m[41m [m }[m [m static float pixelRatio_Window_(const iWindow *d) {[m [36m@@ -308,7 +308,7 @@[m [mstatic iRoot *rootAt_Window_(const iWindow *d, iInt2 coord) {[m }[m [m #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME)[m [31m-static SDL_HitTestResult hitTest_Window_(SDL_Window *win, const SDL_Point *pos, void *data) {[m [32m+[m[32mstatic SDL_HitTestResult hitTest_MainWindow_(SDL_Window *win, const SDL_Point *pos, void *data) {[m iWindow *d = data;[m iAssert(d->win == win);[m if (SDL_GetWindowFlags(d->win) & (SDL_WINDOW_MOUSE_CAPTURE | SDL_WINDOW_FULLSCREEN_DESKTOP)) {[m [36m@@ -361,19 +361,22 @@[m [mSDL_HitTestResult hitTest_Window(const iWindow *d, iInt2 pos) {[m #endif[m [m iBool create_Window_(iWindow *d, iRect rect, uint32_t flags) {[m [31m- flags |= SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN;[m [32m+[m[32m flags |= SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN;[m [32m+[m[32m if (d->type == main_WindowType) {[m [32m+[m[32m flags |= SDL_WINDOW_RESIZABLE;[m #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME)[m [31m- if (prefs_App()->customFrame) {[m [31m- /* We are drawing a custom frame so hide the default one. */[m [31m- flags |= SDL_WINDOW_BORDERLESS;[m [31m- }[m [32m+[m[32m if (prefs_App()->customFrame) {[m [32m+[m[32m /* We are drawing a custom frame so hide the default one. */[m [32m+[m[32m flags |= SDL_WINDOW_BORDERLESS;[m [32m+[m[32m }[m #endif[m [32m+[m[32m }[m if (SDL_CreateWindowAndRenderer([m width_Rect(rect), height_Rect(rect), flags, &d->win, &d->render)) {[m return iFalse;[m }[m #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME)[m [31m- if (prefs_App()->customFrame) {[m [32m+[m[32m if (type_Window(d) == main_WindowType && prefs_App()->customFrame) {[m /* Register a handler for window hit testing (drag, resize). */[m SDL_SetWindowHitTest(d->win, hitTest_Window_, d);[m SDL_SetWindowResizable(d->win, SDL_TRUE);[m [36m@@ -397,40 +400,28 @@[m [mstatic SDL_Surface *loadImage_(const iBlock *data, int resized) {[m pixels, w, h, 8 * num, w * num, SDL_PIXELFORMAT_RGBA32);[m }[m [m [31m-void init_Window(iWindow *d, iRect rect) {[m [31m- theWindow_ = d;[m [31m- d->win = NULL;[m [31m- d->size = zero_I2(); /* will be updated below */[m [31m- iZap(d->roots);[m [31m- d->splitMode = d->pendingSplitMode = 0;[m [31m- d->pendingSplitUrl = new_String();[m [31m- d->hover = NULL;[m [31m- d->lastHover = NULL;[m [31m- d->mouseGrab = NULL;[m [31m- d->focus = NULL;[m [31m- iZap(d->cursors);[m [31m- d->place.initialPos = rect.pos;[m [31m- d->place.normalRect = rect;[m [31m- d->place.lastNotifiedSize = zero_I2();[m [31m- d->place.snap = 0;[m [32m+[m[32mvoid init_Window(iWindow *d, enum iWindowType type, iRect rect, uint32_t flags) {[m [32m+[m[32m d->type = type;[m [32m+[m[32m d->win = NULL;[m [32m+[m[32m d->size = zero_I2(); /* will be updated below */[m [32m+[m[32m d->hover = NULL;[m [32m+[m[32m d->lastHover = NULL;[m [32m+[m[32m d->mouseGrab = NULL;[m [32m+[m[32m d->focus = NULL;[m d->pendingCursor = NULL;[m [31m- d->isDrawFrozen = iTrue;[m [31m- d->isExposed = iFalse;[m [31m- d->isMinimized = iFalse;[m [32m+[m[32m d->isDrawFrozen = iTrue;[m [32m+[m[32m d->isExposed = iFalse;[m [32m+[m[32m d->isMinimized = iFalse;[m d->isInvalidated = iFalse; /* set when posting event, to avoid repeated events */[m [31m- d->isMouseInside = iTrue; [m [31m- d->ignoreClick = iFalse;[m [32m+[m[32m d->isMouseInside = iTrue;[m [32m+[m[32m d->ignoreClick = iFalse;[m d->focusGainedAt = 0;[m [31m- d->keyboardHeight = 0;[m [31m- uint32_t flags = 0;[m [31m-#if defined (iPlatformAppleDesktop)[m [31m- SDL_SetHint(SDL_HINT_RENDER_DRIVER, shouldDefaultToMetalRenderer_MacOS() ? "metal" : "opengl");[m [31m-#elif defined (iPlatformAppleMobile)[m [31m- SDL_SetHint(SDL_HINT_RENDER_DRIVER, "metal");[m [31m-#else[m [31m- flags |= SDL_WINDOW_OPENGL;[m [31m-#endif[m [31m- SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1");[m [32m+[m[32m d->presentTime = 0.0;[m [32m+[m[32m d->frameTime = SDL_GetTicks();[m [32m+[m[32m d->keyRoot = NULL;[m [32m+[m[32m d->borderShadow = NULL;[m [32m+[m[32m iZap(d->roots);[m [32m+[m[32m iZap(d->cursors);[m /* First try SDL's default renderer that should be the best option. */[m if (forceSoftwareRender_App() || !create_Window_(d, rect, flags)) {[m /* No luck, maybe software only? This should always work as long as there is a display. */[m [36m@@ -443,40 +434,74 @@[m [mvoid init_Window(iWindow *d, iRect rect) {[m if (left_Rect(rect) >= 0 || top_Rect(rect) >= 0) {[m SDL_SetWindowPosition(d->win, left_Rect(rect), top_Rect(rect));[m }[m [31m-#if defined (iPlatformMobile)[m [32m+[m[32m SDL_GetRendererOutputSize(d->render, &d->size.x, &d->size.y);[m[41m [m [32m+[m[32m drawBlank_Window_(d);[m [32m+[m[32m d->pixelRatio = pixelRatio_Window_(d); /* point/pixel conversion */[m [32m+[m[32m d->displayScale = displayScale_Window_(d);[m [32m+[m[32m d->uiScale = initialUiScale_;[m [32m+[m[32m /* TODO: Ratios, scales, and metrics must be window-specific, not global. */[m [32m+[m[32m setScale_Metrics(d->pixelRatio * d->displayScale * d->uiScale);[m [32m+[m[32m}[m [32m+[m [32m+[m[32mvoid deinit_Window(iWindow *d) {[m [32m+[m[32m SDL_DestroyRenderer(d->render);[m [32m+[m[32m SDL_DestroyWindow(d->win);[m [32m+[m[32m iForIndices(i, d->cursors) {[m [32m+[m[32m if (d->cursors[i]) {[m [32m+[m[32m SDL_FreeCursor(d->cursors[i]);[m [32m+[m[32m }[m [32m+[m[32m }[m[41m [m [32m+[m[32m}[m [32m+[m [32m+[m[32mvoid init_MainWindow(iMainWindow *d, iRect rect) {[m [32m+[m[32m theWindow_ = &d->base;[m [32m+[m[32m uint32_t flags = 0;[m [32m+[m[32m#if defined (iPlatformAppleDesktop)[m [32m+[m[32m SDL_SetHint(SDL_HINT_RENDER_DRIVER, shouldDefaultToMetalRenderer_MacOS() ? "metal" : "opengl");[m [32m+[m[32m#elif defined (iPlatformAppleMobile)[m [32m+[m[32m SDL_SetHint(SDL_HINT_RENDER_DRIVER, "metal");[m [32m+[m[32m#else[m [32m+[m[32m flags |= SDL_WINDOW_OPENGL;[m [32m+[m[32m#endif[m [32m+[m[32m SDL_SetHint(SDL_HINT_RENDER_VSYNC, "1");[m [32m+[m[32m init_Window(&d->base, main_WindowType, rect, flags);[m [32m+[m[32m d->splitMode = d->pendingSplitMode = 0;[m [32m+[m[32m d->pendingSplitUrl = new_String();[m [32m+[m[32m d->place.initialPos = rect.pos;[m [32m+[m[32m d->place.normalRect = rect;[m [32m+[m[32m d->place.lastNotifiedSize = zero_I2();[m [32m+[m[32m d->place.snap = 0;[m [32m+[m[32m d->keyboardHeight = 0;[m [32m+[m[32m#if defined(iPlatformMobile)[m const iInt2 minSize = zero_I2(); /* windows aren't independently resizable */[m #else[m const iInt2 minSize = init_I2(425, 325);[m #endif[m [31m- SDL_SetWindowMinimumSize(d->win, minSize.x, minSize.y);[m [31m- SDL_SetWindowTitle(d->win, "Lagrange");[m [32m+[m[32m SDL_SetWindowMinimumSize(d->base.win, minSize.x, minSize.y);[m [32m+[m[32m SDL_SetWindowTitle(d->base.win, "Lagrange");[m /* Some info. */ {[m SDL_RendererInfo info;[m [31m- SDL_GetRendererInfo(d->render, &info);[m [32m+[m[32m SDL_GetRendererInfo(d->base.render, &info);[m isOpenGLRenderer_ = !iCmpStr(info.name, "opengl");[m [31m- printf("[window] renderer: %s%s\n", info.name,[m [32m+[m[32m printf("[window] renderer: %s%s\n",[m [32m+[m[32m info.name,[m info.flags & SDL_RENDERER_ACCELERATED ? " (accelerated)" : "");[m [31m-#if !defined (NDEBUG)[m [32m+[m[32m#if !defined(NDEBUG)[m printf("[window] max texture size: %d x %d\n",[m info.max_texture_width,[m info.max_texture_height);[m for (size_t i = 0; i < info.num_texture_formats; ++i) {[m [31m- printf("[window] supported texture format: %s\n", SDL_GetPixelFormatName([m [31m- info.texture_formats[i]));[m [32m+[m[32m printf("[window] supported texture format: %s\n",[m [32m+[m[32m SDL_GetPixelFormatName(info.texture_formats[i]));[m }[m #endif[m }[m [31m- drawBlank_Window_(d);[m [31m- d->pixelRatio = pixelRatio_Window_(d); /* point/pixel conversion */[m [31m- d->displayScale = displayScale_Window_(d);[m [31m- d->uiScale = initialUiScale_;[m [31m- setScale_Metrics(d->pixelRatio * d->displayScale * d->uiScale);[m [31m-#if defined (iPlatformMsys)[m [31m- SDL_SetWindowMinimumSize(d->win, minSize.x * d->displayScale, minSize.y * d->displayScale);[m [31m- useExecutableIconResource_SDLWindow(d->win);[m [32m+[m[32m#if defined(iPlatformMsys)[m [32m+[m[32m SDL_SetWindowMinimumSize(d->win, minSize.x * d->base.displayScale, minSize.y * d->base.displayScale);[m [32m+[m[32m useExecutableIconResource_SDLWindow(d->base.win);[m #endif[m #if defined (iPlatformLinux)[m [31m- SDL_SetWindowMinimumSize(d->win, minSize.x * d->pixelRatio, minSize.y * d->pixelRatio);[m [32m+[m[32m SDL_SetWindowMinimumSize(d->win, minSize.x * d->base.pixelRatio, minSize.y * d->base.pixelRatio);[m /* Load the window icon. */ {[m SDL_Surface *surf = loadImage_(&imageLagrange64_Embedded, 0);[m SDL_SetWindowIcon(d->win, surf);[m [36m@@ -487,18 +512,14 @@[m [mvoid init_Window(iWindow *d, iRect rect) {[m #if defined (iPlatformAppleMobile)[m setupWindow_iOS(d);[m #endif[m [31m- d->presentTime = 0.0;[m [31m- d->frameTime = SDL_GetTicks();[m [31m- d->loadAnimTimer = 0;[m [31m- init_Text(d->render);[m [31m- SDL_GetRendererOutputSize(d->render, &d->size.x, &d->size.y);[m [31m- setupUserInterface_Window(d);[m [32m+[m[32m init_Text(d->base.render);[m [32m+[m[32m SDL_GetRendererOutputSize(d->base.render, &d->base.size.x, &d->base.size.y);[m[41m [m [32m+[m[32m setupUserInterface_MainWindow(d);[m postCommand_App("~bindings.changed"); /* update from bindings */[m [31m- //updateSize_Window_(d, iFalse);[m /* Load the border shadow texture. */ {[m SDL_Surface *surf = loadImage_(&imageShadow_Embedded, 0);[m [31m- d->borderShadow = SDL_CreateTextureFromSurface(d->render, surf);[m [31m- SDL_SetTextureBlendMode(d->borderShadow, SDL_BLENDMODE_BLEND);[m [32m+[m[32m d->base.borderShadow = SDL_CreateTextureFromSurface(d->base.render, surf);[m [32m+[m[32m SDL_SetTextureBlendMode(d->base.borderShadow, SDL_BLENDMODE_BLEND);[m free(surf->pixels);[m SDL_FreeSurface(surf);[m }[m [36m@@ -508,7 +529,7 @@[m [mvoid init_Window(iWindow *d, iRect rect) {[m if (prefs_App()->customFrame) {[m SDL_Surface *surf = loadImage_(&imageLagrange64_Embedded, appIconSize_Root());[m SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0");[m [31m- d->appIcon = SDL_CreateTextureFromSurface(d->render, surf);[m [32m+[m[32m d->appIcon = SDL_CreateTextureFromSurface(d->base.render, surf);[m free(surf->pixels);[m SDL_FreeSurface(surf);[m /* We need to observe non-client-area events. */[m [36m@@ -517,7 +538,7 @@[m [mvoid init_Window(iWindow *d, iRect rect) {[m #endif[m }[m [m [31m-void deinit_Window(iWindow *d) {[m [32m+[m[32mstatic void deinitRoots_Window_(iWindow *d) {[m iRecycle();[m iForIndices(i, d->roots) {[m if (d->roots[i]) {[m [36m@@ -525,19 +546,17 @@[m [mvoid deinit_Window(iWindow *d) {[m deinit_Root(d->roots[i]);[m }[m }[m [31m- if (theWindow_ == d) {[m [32m+[m[32m setCurrent_Root(NULL);[m [32m+[m[32m}[m [32m+[m [32m+[m[32mvoid deinit_MainWindow(iMainWindow *d) {[m [32m+[m[32m deinitRoots_Window_(as_Window(d));[m [32m+[m[32m if (theWindow_ == as_Window(d)) {[m theWindow_ = NULL;[m }[m [31m- setCurrent_Root(NULL);[m delete_String(d->pendingSplitUrl);[m deinit_Text();[m [31m- SDL_DestroyRenderer(d->render);[m [31m- SDL_DestroyWindow(d->win);[m [31m- iForIndices(i, d->cursors) {[m [31m- if (d->cursors[i]) {[m [31m- SDL_FreeCursor(d->cursors[i]);[m [31m- }[m [31m- }[m [32m+[m[32m deinit_Window(&d->base);[m }[m [m SDL_Renderer *renderer_Window(const iWindow *d) {[m [36m@@ -550,8 +569,8 @@[m [miInt2 maxTextureSize_Window(const iWindow *d) {[m return init_I2(info.max_texture_width, info.max_texture_height);[m }[m [m [31m-iBool isFullscreen_Window(const iWindow *d) {[m [31m- return snap_Window(d) == fullscreen_WindowSnap;[m [32m+[m[32miBool isFullscreen_MainWindow(const iMainWindow *d) {[m [32m+[m[32m return snap_MainWindow(d) == fullscreen_WindowSnap;[m }[m [m iRoot *findRoot_Window(const iWindow *d, const iWidget *widget) {[m [36m@@ -570,36 +589,41 @@[m [miRoot *otherRoot_Window(const iWindow *d, iRoot *root) {[m return root == d->roots[0] && d->roots[1] ? d->roots[1] : d->roots[0];[m }[m [m [31m-static void invalidate_Window_(iWindow *d, iBool forced) {[m [31m- if (d && (!d->isInvalidated || forced)) {[m [31m- d->isInvalidated = iTrue;[m [32m+[m[32mstatic void invalidate_MainWindow_(iMainWindow *d, iBool forced) {[m [32m+[m[32m if (d && (!d->base.isInvalidated || forced)) {[m [32m+[m[32m d->base.isInvalidated = iTrue;[m resetFonts_Text();[m postCommand_App("theme.changed auto:1"); /* forces UI invalidation */[m }[m }[m [m [31m-void invalidate_Window(iWindow *d) {[m [31m- invalidate_Window_(d, iFalse);[m [32m+[m[32mvoid invalidate_Window(iAnyWindow *d) {[m [32m+[m[32m if (type_Window(d) == main_WindowType) {[m [32m+[m[32m invalidate_MainWindow_(as_MainWindow(d), iFalse);[m [32m+[m[32m }[m [32m+[m[32m else {[m [32m+[m[32m iAssert(type_Window(d) == main_WindowType);[m [32m+[m[32m }[m }[m [m [31m-static iBool isNormalPlacement_Window_(const iWindow *d) {[m [31m- if (d->isDrawFrozen) return iFalse;[m [32m+[m[32mstatic iBool isNormalPlacement_MainWindow_(const iMainWindow *d) {[m [32m+[m[32m if (d->base.isDrawFrozen) return iFalse;[m #if defined (iPlatformApple)[m /* Maximized mode is not special on macOS. */[m [31m- if (snap_Window(d) == maximized_WindowSnap) {[m [32m+[m[32m if (snap_MainWindow(d) == maximized_WindowSnap) {[m return iTrue;[m }[m #endif[m [31m- if (snap_Window(d)) return iFalse;[m [31m- return !(SDL_GetWindowFlags(d->win) & SDL_WINDOW_MINIMIZED);[m [32m+[m[32m if (snap_MainWindow(d)) return iFalse;[m [32m+[m[32m return !(SDL_GetWindowFlags(d->base.win) & SDL_WINDOW_MINIMIZED);[m }[m [m [31m-static iBool unsnap_Window_(iWindow *d, const iInt2 *newPos) {[m [32m+[m[32mstatic iBool unsnap_MainWindow_(iMainWindow *d, const iInt2 *newPos) {[m #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME)[m if (!prefs_App()->customFrame) {[m return iFalse;[m }[m [31m- const int snap = snap_Window(d);[m [32m+[m[32m const int snap = snap_MainWindow(d);[m if (snap == yMaximized_WindowSnap || snap == left_WindowSnap || snap == right_WindowSnap) {[m if (!newPos || (d->place.lastHit == SDL_HITTEST_RESIZE_LEFT ||[m d->place.lastHit == SDL_HITTEST_RESIZE_RIGHT)) {[m [36m@@ -607,21 +631,21 @@[m [mstatic iBool unsnap_Window_(iWindow *d, const iInt2 *newPos) {[m }[m if (newPos) {[m SDL_Rect usable;[m [31m- SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->win), &usable);[m [32m+[m[32m SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->base.win), &usable);[m /* Snap to top. */[m if (snap == yMaximized_WindowSnap &&[m iAbs(newPos->y - usable.y) < lineHeight_Text(uiContent_FontId) * 2) {[m [31m- setSnap_Window(d, redo_WindowSnap | yMaximized_WindowSnap);[m [32m+[m[32m setSnap_MainWindow(d, redo_WindowSnap | yMaximized_WindowSnap);[m return iFalse;[m }[m }[m }[m if (snap && snap != fullscreen_WindowSnap) {[m [31m- if (snap_Window(d) == yMaximized_WindowSnap && newPos) {[m [32m+[m[32m if (snap_MainWindow(d) == yMaximized_WindowSnap && newPos) {[m d->place.normalRect.pos = *newPos;[m }[m //printf("unsnap\n"); fflush(stdout);[m [31m- setSnap_Window(d, none_WindowSnap);[m [32m+[m[32m setSnap_MainWindow(d, none_WindowSnap);[m return iTrue;[m }[m #endif[m [36m@@ -652,109 +676,110 @@[m [mstatic void checkPixelRatioChange_Window_(iWindow *d) {[m }[m }[m [m [31m-static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) {[m [32m+[m[32mstatic iBool handleWindowEvent_MainWindow_(iMainWindow *d, const SDL_WindowEvent *ev) {[m switch (ev->event) {[m [31m-#if defined (iPlatformDesktop)[m [32m+[m[32m#if defined(iPlatformDesktop)[m case SDL_WINDOWEVENT_EXPOSED:[m [31m- if (!d->isExposed) {[m [31m- drawBlank_Window_(d); /* avoid showing system-provided contents */[m [31m- d->isExposed = iTrue;[m [32m+[m[32m if (!d->base.isExposed) {[m [32m+[m[32m drawBlank_Window_(as_Window(d)); /* avoid showing system-provided contents */[m [32m+[m[32m d->base.isExposed = iTrue;[m }[m /* Since we are manually controlling when to redraw the window, we are responsible[m [31m- for ensuring that window contents get redrawn after expose events. Under certain[m [31m- circumstances (e.g., under openbox), not doing this would mean that the window[m [31m- is missing contents until other events trigger a refresh. */[m [32m+[m[32m for ensuring that window contents get redrawn after expose events. Under certain[m [32m+[m[32m circumstances (e.g., under openbox), not doing this would mean that the window[m [32m+[m[32m is missing contents until other events trigger a refresh. */[m postRefresh_App();[m [31m-#if defined (LAGRANGE_ENABLE_WINDOWPOS_FIX)[m [32m+[m[32m#if defined(LAGRANGE_ENABLE_WINDOWPOS_FIX)[m if (d->place.initialPos.x >= 0) {[m int bx, by;[m SDL_GetWindowBordersSize(d->win, &by, &bx, NULL, NULL);[m [31m- SDL_SetWindowPosition(d->win, d->place.initialPos.x + bx, d->place.initialPos.y + by);[m [32m+[m[32m SDL_SetWindowPosition([m [32m+[m[32m d->win, d->place.initialPos.x + bx, d->place.initialPos.y + by);[m d->place.initialPos = init1_I2(-1);[m }[m #endif[m return iFalse;[m case SDL_WINDOWEVENT_MOVED: {[m [31m- if (d->isMinimized) {[m [32m+[m[32m if (d->base.isMinimized) {[m return iFalse;[m }[m [31m- checkPixelRatioChange_Window_(d);[m [32m+[m[32m checkPixelRatioChange_Window_(as_Window(d));[m const iInt2 newPos = init_I2(ev->data1, ev->data2);[m if (isEqual_I2(newPos, init1_I2(-32000))) { /* magic! */[m /* Maybe minimized? Seems like a Windows constant of some kind. */[m [31m- d->isMinimized = iTrue;[m [32m+[m[32m d->base.isMinimized = iTrue;[m return iFalse;[m }[m [31m-#if defined (LAGRANGE_ENABLE_CUSTOM_FRAME)[m [32m+[m[32m#if defined(LAGRANGE_ENABLE_CUSTOM_FRAME)[m /* Set the snap position depending on where the mouse cursor is. */[m if (prefs_App()->customFrame) {[m SDL_Rect usable;[m [31m- iInt2 mouse = cursor_Win32(); /* SDL is unaware of the current cursor pos */[m [31m- SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->win), &usable);[m [31m- const iBool isTop = iAbs(mouse.y - usable.y) < gap_UI * 20;[m [32m+[m[32m iInt2 mouse = cursor_Win32(); /* SDL is unaware of the current cursor pos */[m [32m+[m[32m SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->base.win), &usable);[m [32m+[m[32m const iBool isTop = iAbs(mouse.y - usable.y) < gap_UI * 20;[m const iBool isBottom = iAbs(usable.y + usable.h - mouse.y) < gap_UI * 20;[m if (iAbs(mouse.x - usable.x) < gap_UI) {[m [31m- setSnap_Window(d,[m [31m- redo_WindowSnap | left_WindowSnap |[m [31m- (isTop ? topBit_WindowSnap : 0) |[m [31m- (isBottom ? bottomBit_WindowSnap : 0));[m [32m+[m[32m setSnap_MainWindow(d,[m [32m+[m[32m redo_WindowSnap | left_WindowSnap |[m [32m+[m[32m (isTop ? topBit_WindowSnap : 0) |[m [32m+[m[32m (isBottom ? bottomBit_WindowSnap : 0));[m return iTrue;[m }[m if (iAbs(mouse.x - usable.x - usable.w) < gap_UI) {[m [31m- setSnap_Window(d,[m [31m- redo_WindowSnap | right_WindowSnap |[m [31m- (isTop ? topBit_WindowSnap : 0) |[m [31m- (isBottom ? bottomBit_WindowSnap : 0));[m [32m+[m[32m setSnap_MainWindow(d,[m [32m+[m[32m redo_WindowSnap | right_WindowSnap |[m [32m+[m[32m (isTop ? topBit_WindowSnap : 0) |[m [32m+[m[32m (isBottom ? bottomBit_WindowSnap : 0));[m return iTrue;[m }[m if (iAbs(mouse.y - usable.y) < 2) {[m [31m- setSnap_Window(d,[m [31m- redo_WindowSnap | (d->place.lastHit == SDL_HITTEST_RESIZE_TOP[m [31m- ? yMaximized_WindowSnap[m [31m- : maximized_WindowSnap));[m [32m+[m[32m setSnap_MainWindow(d,[m [32m+[m[32m redo_WindowSnap | (d->place.lastHit == SDL_HITTEST_RESIZE_TOP[m [32m+[m[32m ? yMaximized_WindowSnap[m [32m+[m[32m : maximized_WindowSnap));[m return iTrue;[m }[m }[m #endif /* defined LAGRANGE_ENABLE_CUSTOM_FRAME */[m [31m- if (unsnap_Window_(d, &newPos)) {[m [32m+[m[32m if (unsnap_MainWindow_(d, &newPos)) {[m return iTrue;[m }[m [31m- if (isNormalPlacement_Window_(d)) {[m [32m+[m[32m if (isNormalPlacement_MainWindow_(d)) {[m d->place.normalRect.pos = newPos;[m [31m- //printf("normal rect set (move)\n"); fflush(stdout);[m [32m+[m[32m // printf("normal rect set (move)\n"); fflush(stdout);[m iInt2 border = zero_I2();[m [31m-#if !defined (iPlatformApple)[m [32m+[m[32m#if !defined(iPlatformApple)[m SDL_GetWindowBordersSize(d->win, &border.y, &border.x, NULL, NULL);[m #endif[m [31m- d->place.normalRect.pos = max_I2(zero_I2(), sub_I2(d->place.normalRect.pos, border));[m [32m+[m[32m d->place.normalRect.pos =[m [32m+[m[32m max_I2(zero_I2(), sub_I2(d->place.normalRect.pos, border));[m }[m return iTrue;[m }[m case SDL_WINDOWEVENT_RESIZED:[m [31m- if (d->isMinimized) {[m [31m- //updateSize_Window_(d, iTrue);[m [32m+[m[32m if (d->base.isMinimized) {[m [32m+[m[32m // updateSize_Window_(d, iTrue);[m return iTrue;[m }[m [31m- if (unsnap_Window_(d, NULL)) {[m [32m+[m[32m if (unsnap_MainWindow_(d, NULL)) {[m return iTrue;[m }[m [31m- if (isNormalPlacement_Window_(d)) {[m [32m+[m[32m if (isNormalPlacement_MainWindow_(d)) {[m d->place.normalRect.size = init_I2(ev->data1, ev->data2);[m [31m- //printf("normal rect set (resize)\n"); fflush(stdout);[m [32m+[m[32m // printf("normal rect set (resize)\n"); fflush(stdout);[m }[m [31m- checkPixelRatioChange_Window_(d);[m [31m- //updateSize_Window_(d, iTrue /* we were already redrawing during the resize */);[m [32m+[m[32m checkPixelRatioChange_Window_(as_Window(d));[m postRefresh_App();[m return iTrue;[m case SDL_WINDOWEVENT_RESTORED:[m case SDL_WINDOWEVENT_SHOWN:[m [31m- updateSize_Window_(d, iTrue);[m [31m- invalidate_Window_(d, iTrue);[m [31m- d->isMinimized = iFalse;[m [32m+[m[32m updateSize_MainWindow_(d, iTrue);[m [32m+[m[32m invalidate_MainWindow_(d, iTrue);[m [32m+[m[32m d->base.isMinimized = iFalse;[m postRefresh_App();[m return iTrue;[m case SDL_WINDOWEVENT_MINIMIZED:[m [31m- d->isMinimized = iTrue;[m [32m+[m[32m d->base.isMinimized = iTrue;[m return iTrue;[m #else /* if defined (!iPlatformDesktop) */[m case SDL_WINDOWEVENT_RESIZED:[m [36m@@ -765,19 +790,19 @@[m [mstatic iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) {[m #endif[m case SDL_WINDOWEVENT_LEAVE:[m unhover_Widget();[m [31m- d->isMouseInside = iFalse;[m [32m+[m[32m d->base.isMouseInside = iFalse;[m postCommand_App("window.mouse.exited");[m return iTrue;[m case SDL_WINDOWEVENT_ENTER:[m [31m- d->isMouseInside = iTrue;[m [32m+[m[32m d->base.isMouseInside = iTrue;[m postCommand_App("window.mouse.entered");[m return iTrue;[m case SDL_WINDOWEVENT_FOCUS_GAINED:[m [31m- d->focusGainedAt = SDL_GetTicks();[m [32m+[m[32m d->base.focusGainedAt = SDL_GetTicks();[m setCapsLockDown_Keys(iFalse);[m postCommand_App("window.focus.gained");[m [31m- d->isExposed = iTrue;[m [31m-#if !defined (iPlatformDesktop)[m [32m+[m[32m d->base.isExposed = iTrue;[m [32m+[m[32m#if !defined(iPlatformDesktop)[m /* Returned to foreground, may have lost buffered content. */[m invalidate_Window_(d, iTrue);[m postCommand_App("window.unfreeze");[m [36m@@ -785,12 +810,12 @@[m [mstatic iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) {[m return iFalse;[m case SDL_WINDOWEVENT_FOCUS_LOST:[m postCommand_App("window.focus.lost");[m [31m-#if !defined (iPlatformDesktop)[m [32m+[m[32m#if !defined(iPlatformDesktop)[m setFreezeDraw_Window(d, iTrue);[m #endif[m return iFalse;[m case SDL_WINDOWEVENT_TAKE_FOCUS:[m [31m- SDL_SetWindowInputFocus(d->win);[m [32m+[m[32m SDL_SetWindowInputFocus(d->base.win);[m postRefresh_App();[m return iTrue;[m default:[m [36m@@ -806,7 +831,8 @@[m [mstatic void applyCursor_Window_(iWindow *d) {[m }[m }[m [m [31m-iBool processEvent_Window(iWindow *d, const SDL_Event *ev) {[m [32m+[m[32miBool processEvent_MainWindow(iMainWindow *d, const SDL_Event *ev) {[m [32m+[m[32m iWindow *w = as_Window(d);[m switch (ev->type) {[m #if defined (LAGRANGE_ENABLE_CUSTOM_FRAME)[m case SDL_SYSWMEVENT: {[m [36m@@ -819,19 +845,19 @@[m [miBool processEvent_Window(iWindow *d, const SDL_Event *ev) {[m }[m #endif[m case SDL_WINDOWEVENT: {[m [31m- return handleWindowEvent_Window_(d, &ev->window);[m [32m+[m[32m return handleWindowEvent_MainWindow_(d, &ev->window);[m }[m case SDL_RENDER_TARGETS_RESET:[m case SDL_RENDER_DEVICE_RESET: {[m [31m- invalidate_Window_(d, iTrue /* force full reset */);[m [32m+[m[32m invalidate_MainWindow_(d, iTrue /* force full reset */);[m break;[m }[m default: {[m SDL_Event event = *ev;[m if (event.type == SDL_USEREVENT && isCommand_UserEvent(ev, "window.unfreeze")) {[m [31m- d->isDrawFrozen = iFalse;[m [31m- if (SDL_GetWindowFlags(d->win) & SDL_WINDOW_HIDDEN) {[m [31m- SDL_ShowWindow(d->win);[m [32m+[m[32m d->base.isDrawFrozen = iFalse;[m [32m+[m[32m if (SDL_GetWindowFlags(w->win) & SDL_WINDOW_HIDDEN) {[m [32m+[m[32m SDL_ShowWindow(w->win);[m }[m postRefresh_App();[m postCommand_App("media.player.update"); /* in case a player needs updating */[m [36m@@ -840,35 +866,35 @@[m [miBool processEvent_Window(iWindow *d, const SDL_Event *ev) {[m if (processEvent_Touch(&event)) {[m return iTrue;[m }[m [31m- if (event.type == SDL_KEYDOWN && SDL_GetTicks() - d->focusGainedAt < 10) {[m [32m+[m[32m if (event.type == SDL_KEYDOWN && SDL_GetTicks() - d->base.focusGainedAt < 10) {[m /* Suspiciously close to when input focus was received. For example under openbox,[m closing xterm with Ctrl+D will cause the keydown event to "spill" over to us.[m As a workaround, ignore these events. */[m return iTrue; /* won't go to bindings, either */[m }[m [31m- if (event.type == SDL_MOUSEBUTTONDOWN && d->ignoreClick) {[m [31m- d->ignoreClick = iFalse;[m [32m+[m[32m if (event.type == SDL_MOUSEBUTTONDOWN && d->base.ignoreClick) {[m [32m+[m[32m d->base.ignoreClick = iFalse;[m return iTrue;[m }[m /* Map mouse pointer coordinate to our coordinate system. */[m if (event.type == SDL_MOUSEMOTION) {[m [31m- setCursor_Window(d, SDL_SYSTEM_CURSOR_ARROW); /* default cursor */[m [31m- const iInt2 pos = coord_Window(d, event.motion.x, event.motion.y);[m [32m+[m[32m setCursor_Window(w, SDL_SYSTEM_CURSOR_ARROW); /* default cursor */[m [32m+[m[32m const iInt2 pos = coord_Window(w, event.motion.x, event.motion.y);[m event.motion.x = pos.x;[m event.motion.y = pos.y;[m }[m else if (event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEBUTTONDOWN) {[m [31m- const iInt2 pos = coord_Window(d, event.button.x, event.button.y);[m [32m+[m[32m const iInt2 pos = coord_Window(w, event.button.x, event.button.y);[m event.button.x = pos.x;[m event.button.y = pos.y;[m if (event.type == SDL_MOUSEBUTTONDOWN) {[m /* Button clicks will change keyroot. */[m [31m- if (numRoots_Window(d) > 1) {[m [32m+[m[32m if (numRoots_Window(w) > 1) {[m const iInt2 click = init_I2(event.button.x, event.button.y);[m [31m- iForIndices(i, d->roots) {[m [31m- iRoot *root = d->roots[i];[m [31m- if (root != d->keyRoot && contains_Rect(rect_Root(root), click)) {[m [31m- setKeyRoot_Window(d, root);[m [32m+[m[32m iForIndices(i, w->roots) {[m [32m+[m[32m iRoot *root = w->roots[i];[m [32m+[m[32m if (root != w->keyRoot && contains_Rect(rect_Root(root), click)) {[m [32m+[m[32m setKeyRoot_Window(w, root);[m break;[m }[m }[m [36m@@ -883,13 +909,13 @@[m [miBool processEvent_Window(iWindow *d, const SDL_Event *ev) {[m event.type == SDL_MOUSEBUTTONUP || event.type == SDL_MOUSEBUTTONDOWN) {[m if (mouseGrab_Widget()) {[m iWidget *grabbed = mouseGrab_Widget();[m [31m- setCurrent_Root(findRoot_Window(d, grabbed));[m [32m+[m[32m setCurrent_Root(findRoot_Window(w, grabbed));[m wasUsed = dispatchEvent_Widget(grabbed, &event);[m }[m }[m /* Dispatch the event to the tree of widgets. */[m if (!wasUsed) {[m [31m- wasUsed = dispatchEvent_Window(d, &event);[m [32m+[m[32m wasUsed = dispatchEvent_Window(w, &event);[m }[m if (!wasUsed) {[m /* As a special case, clicking the middle mouse button can be used for pasting[m [36m@@ -902,17 +928,17 @@[m [miBool processEvent_Window(iWindow *d, const SDL_Event *ev) {[m paste.key.keysym.mod = KMOD_PRIMARY;[m paste.key.state = SDL_PRESSED;[m paste.key.timestamp = SDL_GetTicks();[m [31m- wasUsed = dispatchEvent_Window(d, &paste);[m [32m+[m[32m wasUsed = dispatchEvent_Window(w, &paste);[m }[m if (event.type == SDL_MOUSEBUTTONDOWN && event.button.button == SDL_BUTTON_RIGHT) {[m [31m- if (postContextClick_Window(d, &event.button)) {[m [32m+[m[32m if (postContextClick_Window(w, &event.button)) {[m wasUsed = iTrue;[m }[m }[m }[m if (isMetricsChange_UserEvent(&event)) {[m [31m- iForIndices(i, d->roots) {[m [31m- updateMetrics_Root(d->roots[i]);[m [32m+[m[32m iForIndices(i, w->roots) {[m [32m+[m[32m updateMetrics_Root(w->roots[i]);[m }[m }[m if (isCommand_UserEvent(&event, "lang.changed")) {[m [36m@@ -921,16 +947,16 @@[m [miBool processEvent_Window(iWindow *d, const SDL_Event *ev) {[m removeMacMenus_();[m insertMacMenus_();[m #endif[m [31m- invalidate_Window(d);[m [31m- iForIndices(i, d->roots) {[m [31m- if (d->roots[i]) {[m [31m- updatePreferencesLayout_Widget(findChild_Widget(d->roots[i]->widget, "prefs"));[m [31m- arrange_Widget(d->roots[i]->widget);[m [32m+[m[32m invalidate_Window(w);[m [32m+[m[32m iForIndices(i, w->roots) {[m [32m+[m[32m if (w->roots[i]) {[m [32m+[m[32m updatePreferencesLayout_Widget(findChild_Widget(w->roots[i]->widget, "prefs"));[m [32m+[m[32m arrange_Widget(w->roots[i]->widget);[m }[m }[m }[m if (event.type == SDL_MOUSEMOTION) {[m [31m- applyCursor_Window_(d);[m [32m+[m[32m applyCursor_Window_(w);[m }[m return wasUsed;[m }[m [36m@@ -1018,25 +1044,26 @@[m [miBool postContextClick_Window(iWindow *d, const SDL_MouseButtonEvent *ev) {[m return iFalse;[m }[m [m [31m-void draw_Window(iWindow *d) {[m [31m- if (d->isDrawFrozen) {[m [32m+[m[32mvoid draw_MainWindow(iMainWindow *d) {[m [32m+[m[32m iWindow *w = as_Window(d);[m [32m+[m[32m if (w->isDrawFrozen) {[m return;[m }[m /* Check if root needs resizing. */ {[m iInt2 renderSize;[m [31m- SDL_GetRendererOutputSize(d->render, &renderSize.x, &renderSize.y);[m [31m- if (!isEqual_I2(renderSize, d->size)) {[m [31m- updateSize_Window_(d, iTrue);[m [32m+[m[32m SDL_GetRendererOutputSize(w->render, &renderSize.x, &renderSize.y);[m [32m+[m[32m if (!isEqual_I2(renderSize, w->size)) {[m [32m+[m[32m updateSize_MainWindow_(d, iTrue);[m processEvents_App(postedEventsOnly_AppEventMode);[m }[m }[m [31m- const int winFlags = SDL_GetWindowFlags(d->win);[m [32m+[m[32m const int winFlags = SDL_GetWindowFlags(d->base.win);[m const iBool gotFocus = (winFlags & SDL_WINDOW_INPUT_FOCUS) != 0;[m iPaint p;[m init_Paint(&p);[m /* Clear the window. The clear color is visible as a border around the window[m when the custom frame is being used. */ {[m [31m- setCurrent_Root(d->roots[0]);[m [32m+[m[32m setCurrent_Root(w->roots[0]);[m #if defined (iPlatformMobile)[m iColor back = get_Color(uiBackground_ColorId);[m if (deviceType_App() == phone_AppDeviceType) {[m [36m@@ -1050,16 +1077,16 @@[m [mvoid draw_Window(iWindow *d) {[m : uiSeparator_ColorId);[m #endif[m unsetClip_Paint(&p); /* update clip to full window */[m [31m- SDL_SetRenderDrawColor(d->render, back.r, back.g, back.b, 255);[m [31m- SDL_RenderClear(d->render);[m [32m+[m[32m SDL_SetRenderDrawColor(w->render, back.r, back.g, back.b, 255);[m [32m+[m[32m SDL_RenderClear(w->render);[m }[m /* Draw widgets. */[m [31m- d->frameTime = SDL_GetTicks();[m [31m- if (isExposed_Window(d)) {[m [31m- d->isInvalidated = iFalse;[m [32m+[m[32m w->frameTime = SDL_GetTicks();[m [32m+[m[32m if (isExposed_Window(w)) {[m [32m+[m[32m w->isInvalidated = iFalse;[m extern int drawCount_;[m [31m- iForIndices(i, d->roots) {[m [31m- iRoot *root = d->roots[i];[m [32m+[m[32m iForIndices(i, w->roots) {[m [32m+[m[32m iRoot *root = w->roots[i];[m if (root) {[m setCurrent_Root(root);[m unsetClip_Paint(&p); /* update clip to current root */[m [36m@@ -1076,14 +1103,14 @@[m [mvoid draw_Window(iWindow *d) {[m SDL_SetTextureColorMod(d->appIcon, iconColor.r, iconColor.g, iconColor.b);[m SDL_SetTextureAlphaMod(d->appIcon, gotFocus || !isLight ? 255 : 92);[m SDL_RenderCopy([m [31m- d->render,[m [32m+[m[32m w->render,[m d->appIcon,[m NULL,[m &(SDL_Rect){ left_Rect(rect) + gap_UI * 1.25f, mid.y - size / 2, size, size });[m }[m #endif[m /* Root separator and keyboard focus indicator. */[m [31m- if (numRoots_Window(d) > 1){[m [32m+[m[32m if (numRoots_Window(w) > 1){[m const iRect bounds = bounds_Widget(root->widget);[m if (i == 1) {[m fillRect_Paint(&p, (iRect){[m [36m@@ -1091,7 +1118,7 @@[m [mvoid draw_Window(iWindow *d) {[m init_I2(gap_UI / 4, height_Rect(bounds))[m }, uiSeparator_ColorId);[m }[m [31m- if (root == d->keyRoot) {[m [32m+[m[32m if (root == w->keyRoot) {[m const iBool isDark = isDark_ColorTheme(colorTheme_App());[m fillRect_Paint(&p, (iRect){[m topLeft_Rect(bounds),[m [36m@@ -1104,7 +1131,7 @@[m [mvoid draw_Window(iWindow *d) {[m }[m setCurrent_Root(NULL);[m #if !defined (NDEBUG)[m [31m- draw_Text(defaultBold_FontId, safeRect_Root(d->roots[0]).pos, red_ColorId, "%d", drawCount_);[m [32m+[m[32m draw_Text(defaultBold_FontId, safeRect_Root(w->roots[0]).pos, red_ColorId, "%d", drawCount_);[m drawCount_ = 0;[m #endif[m }[m [36m@@ -1116,21 +1143,21 @@[m [mvoid draw_Window(iWindow *d) {[m SDL_RenderCopy(d->render, glyphCache_Text(), NULL, &rect);[m }[m #endif[m [31m- SDL_RenderPresent(d->render);[m [32m+[m[32m SDL_RenderPresent(w->render);[m }[m [m [31m-void resize_Window(iWindow *d, int w, int h) {[m [32m+[m[32mvoid resize_MainWindow(iMainWindow *d, int w, int h) {[m if (w > 0 && h > 0) {[m [31m- SDL_SetWindowSize(d->win, w, h);[m [31m- updateSize_Window_(d, iFalse);[m [32m+[m[32m SDL_SetWindowSize(d->base.win, w, h);[m [32m+[m[32m updateSize_MainWindow_(d, iFalse);[m }[m else {[m [31m- updateSize_Window_(d, iTrue); /* notify always */[m [32m+[m[32m updateSize_MainWindow_(d, iTrue); /* notify always */[m }[m }[m [m [31m-void setTitle_Window(iWindow *d, const iString *title) {[m [31m- SDL_SetWindowTitle(d->win, cstr_String(title));[m [32m+[m[32mvoid setTitle_MainWindow(iMainWindow *d, const iString *title) {[m [32m+[m[32m SDL_SetWindowTitle(d->base.win, cstr_String(title));[m iLabelWidget *bar = findChild_Widget(get_Root()->widget, "winbar.title");[m if (bar) {[m updateText_LabelWidget(bar, title);[m [36m@@ -1204,11 +1231,15 @@[m [miWindow *get_Window(void) {[m return theWindow_;[m }[m [m [32m+[m[32miMainWindow *get_MainWindow(void) {[m [32m+[m[32m return as_MainWindow(theWindow_);[m [32m+[m[32m}[m [32m+[m iBool isOpenGLRenderer_Window(void) {[m return isOpenGLRenderer_;[m }[m [m [31m-void setKeyboardHeight_Window(iWindow *d, int height) {[m [32m+[m[32mvoid setKeyboardHeight_MainWindow(iMainWindow *d, int height) {[m if (d->keyboardHeight != height) {[m d->keyboardHeight = height;[m postCommandf_App("keyboard.changed arg:%d", height);[m [36m@@ -1216,47 +1247,49 @@[m [mvoid setKeyboardHeight_Window(iWindow *d, int height) {[m }[m }[m [m [31m-void checkPendingSplit_Window(iWindow *d) {[m [32m+[m[32mvoid checkPendingSplit_MainWindow(iMainWindow *d) {[m if (d->splitMode != d->pendingSplitMode) {[m [31m- setSplitMode_Window(d, d->pendingSplitMode);[m [32m+[m[32m setSplitMode_MainWindow(d, d->pendingSplitMode);[m }[m }[m [m [31m-void swapRoots_Window(iWindow *d) {[m [31m- if (numRoots_Window(d) == 2) {[m [31m- iSwap(iRoot *, d->roots[0], d->roots[1]);[m [31m- updateSize_Window_(d, iTrue);[m [32m+[m[32mvoid swapRoots_MainWindow(iMainWindow *d) {[m [32m+[m[32m iWindow *w = as_Window(d);[m [32m+[m[32m if (numRoots_Window(w) == 2) {[m [32m+[m[32m iSwap(iRoot *, w->roots[0], w->roots[1]);[m [32m+[m[32m updateSize_MainWindow_(d, iTrue);[m }[m }[m [m [31m-void setSplitMode_Window(iWindow *d, int splitFlags) {[m [32m+[m[32mvoid setSplitMode_MainWindow(iMainWindow *d, int splitFlags) {[m const int splitMode = splitFlags & mode_WindowSplit;[m if (deviceType_App() == phone_AppDeviceType) {[m /* There isn't enough room on the phone. */[m /* TODO: Maybe in landscape only? */[m return;[m }[m [32m+[m[32m iWindow *w = as_Window(d);[m iAssert(current_Root() == NULL);[m if (d->splitMode != splitMode) {[m [31m- int oldCount = numRoots_Window(d);[m [31m- setFreezeDraw_Window(d, iTrue);[m [32m+[m[32m int oldCount = numRoots_Window(w);[m [32m+[m[32m setFreezeDraw_Window(w, iTrue);[m if (oldCount == 2 && splitMode == 0) {[m /* Keep references to the tabs of the second root. */[m [31m- const iDocumentWidget *curPage = document_Root(d->keyRoot);[m [32m+[m[32m const iDocumentWidget *curPage = document_Root(w->keyRoot);[m if (!curPage) {[m /* All tabs closed on that side. */[m [31m- curPage = document_Root(otherRoot_Window(d, d->keyRoot));[m [32m+[m[32m curPage = document_Root(otherRoot_Window(w, w->keyRoot));[m }[m [31m- iObjectList *tabs = listDocuments_App(d->roots[1]);[m [32m+[m[32m iObjectList *tabs = listDocuments_App(w->roots[1]);[m iForEach(ObjectList, i, tabs) {[m [31m- setRoot_Widget(i.object, d->roots[0]);[m [32m+[m[32m setRoot_Widget(i.object, w->roots[0]);[m }[m setFocus_Widget(NULL);[m [31m- delete_Root(d->roots[1]);[m [31m- d->roots[1] = NULL;[m [31m- d->keyRoot = d->roots[0];[m [32m+[m[32m delete_Root(w->roots[1]);[m [32m+[m[32m w->roots[1] = NULL;[m [32m+[m[32m w->keyRoot = w->roots[0];[m /* Move the deleted root's tabs to the first root. */[m [31m- setCurrent_Root(d->roots[0]);[m [32m+[m[32m setCurrent_Root(w->roots[0]);[m iWidget *docTabs = findWidget_Root("doctabs");[m iForEach(ObjectList, j, tabs) {[m appendTabPage_Widget(docTabs, j.object, "", 0, 0);[m [36m@@ -1268,38 +1301,38 @@[m [mvoid setSplitMode_Window(iWindow *d, int splitFlags) {[m }[m else if (splitMode && oldCount == 1) {[m /* Add a second root. */[m [31m- iDocumentWidget *moved = document_Root(d->roots[0]);[m [31m- iAssert(d->roots[1] == NULL);[m [32m+[m[32m iDocumentWidget *moved = document_Root(w->roots[0]);[m [32m+[m[32m iAssert(w->roots[1] == NULL);[m const iBool addToLeft = (prefs_App()->pinSplit == 2);[m size_t newRootIndex = 1;[m if (addToLeft) {[m [31m- iSwap(iRoot *, d->roots[0], d->roots[1]);[m [32m+[m[32m iSwap(iRoot *, w->roots[0], w->roots[1]);[m newRootIndex = 0;[m }[m [31m- d->roots[newRootIndex] = new_Root();[m [31m- d->keyRoot = d->roots[newRootIndex];[m [31m- setCurrent_Root(d->roots[newRootIndex]);[m [31m- createUserInterface_Root(d->roots[newRootIndex]);[m [32m+[m[32m w->roots[newRootIndex] = new_Root();[m [32m+[m[32m w->keyRoot = w->roots[newRootIndex];[m [32m+[m[32m setCurrent_Root(w->roots[newRootIndex]);[m [32m+[m[32m createUserInterface_Root(w->roots[newRootIndex]);[m if (!isEmpty_String(d->pendingSplitUrl)) {[m [31m- postCommandf_Root(d->roots[newRootIndex], "open url:%s",[m [32m+[m[32m postCommandf_Root(w->roots[newRootIndex], "open url:%s",[m cstr_String(d->pendingSplitUrl));[m clear_String(d->pendingSplitUrl);[m }[m else if (~splitFlags & noEvents_WindowSplit) {[m [31m- iWidget *docTabs0 = findChild_Widget(d->roots[newRootIndex ^ 1]->widget, "doctabs");[m [31m- iWidget *docTabs1 = findChild_Widget(d->roots[newRootIndex]->widget, "doctabs");[m [32m+[m[32m iWidget *docTabs0 = findChild_Widget(w->roots[newRootIndex ^ 1]->widget, "doctabs");[m [32m+[m[32m iWidget *docTabs1 = findChild_Widget(w->roots[newRootIndex]->widget, "doctabs");[m /* If the old root has multiple tabs, move the current one to the new split. */[m if (tabCount_Widget(docTabs0) >= 2) {[m int movedIndex = tabPageIndex_Widget(docTabs0, moved);[m removeTabPage_Widget(docTabs0, movedIndex);[m showTabPage_Widget(docTabs0, tabPage_Widget(docTabs0, iMax(movedIndex - 1, 0)));[m iRelease(removeTabPage_Widget(docTabs1, 0)); /* delete the default tab */[m [31m- setRoot_Widget(as_Widget(moved), d->roots[newRootIndex]);[m [32m+[m[32m setRoot_Widget(as_Widget(moved), w->roots[newRootIndex]);[m prependTabPage_Widget(docTabs1, iClob(moved), "", 0, 0);[m postCommandf_App("tabs.switch page:%p", moved);[m }[m else {[m [31m- postCommand_Root(d->roots[newRootIndex], "navigate.home");[m [32m+[m[32m postCommand_Root(w->roots[newRootIndex], "navigate.home");[m }[m }[m setCurrent_Root(NULL);[m [36m@@ -1328,26 +1361,26 @@[m [mvoid setSplitMode_Window(iWindow *d, int splitFlags) {[m }[m #endif[m if (~splitFlags & noEvents_WindowSplit) {[m [31m- updateSize_Window_(d, iTrue);[m [32m+[m[32m updateSize_MainWindow_(d, iTrue);[m postCommand_App("window.unfreeze");[m }[m }[m }[m [m [31m-void setSnap_Window(iWindow *d, int snapMode) {[m [32m+[m[32mvoid setSnap_MainWindow(iMainWindow *d, int snapMode) {[m if (!prefs_App()->customFrame) {[m if (snapMode == maximized_WindowSnap) {[m [31m- SDL_MaximizeWindow(d->win);[m [32m+[m[32m SDL_MaximizeWindow(d->base.win);[m }[m else if (snapMode == fullscreen_WindowSnap) {[m [31m- SDL_SetWindowFullscreen(d->win, SDL_WINDOW_FULLSCREEN_DESKTOP);[m [32m+[m[32m SDL_SetWindowFullscreen(d->base.win, SDL_WINDOW_FULLSCREEN_DESKTOP);[m }[m else {[m [31m- if (snap_Window(d) == fullscreen_WindowSnap) {[m [31m- SDL_SetWindowFullscreen(d->win, 0);[m [32m+[m[32m if (snap_MainWindow(d) == fullscreen_WindowSnap) {[m [32m+[m[32m SDL_SetWindowFullscreen(d->base.win, 0);[m }[m else {[m [31m- SDL_RestoreWindow(d->win);[m [32m+[m[32m SDL_RestoreWindow(d->base.win);[m }[m }[m return;[m [36m@@ -1359,9 +1392,9 @@[m [mvoid setSnap_Window(iWindow *d, int snapMode) {[m const int snapDist = gap_UI * 4;[m iRect newRect = zero_Rect();[m SDL_Rect usable;[m [31m- SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->win), &usable);[m [32m+[m[32m SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->base.win), &usable);[m if (d->place.snap == fullscreen_WindowSnap) {[m [31m- SDL_SetWindowFullscreen(d->win, 0);[m [32m+[m[32m SDL_SetWindowFullscreen(d->base.win, 0);[m }[m d->place.snap = snapMode & ~redo_WindowSnap;[m switch (snapMode & mask_WindowSnap) {[m [36m@@ -1382,8 +1415,8 @@[m [mvoid setSnap_Window(iWindow *d, int snapMode) {[m case yMaximized_WindowSnap:[m newRect.pos.y = 0;[m newRect.size.y = usable.h;[m [31m- SDL_GetWindowSize(d->win, &newRect.size.x, NULL);[m [31m- SDL_GetWindowPosition(d->win, &newRect.pos.x, NULL);[m [32m+[m[32m SDL_GetWindowSize(d->base.win, &newRect.size.x, NULL);[m [32m+[m[32m SDL_GetWindowPosition(d->base.win, &newRect.pos.x, NULL);[m /* Snap the window to left/right edges, if close by. */[m if (iAbs(right_Rect(newRect) - (usable.x + usable.w)) < snapDist) {[m newRect.pos.x = usable.x + usable.w - width_Rect(newRect);[m [36m@@ -1393,7 +1426,7 @@[m [mvoid setSnap_Window(iWindow *d, int snapMode) {[m }[m break;[m case fullscreen_WindowSnap:[m [31m- SDL_SetWindowFullscreen(d->win, SDL_WINDOW_FULLSCREEN_DESKTOP);[m [32m+[m[32m SDL_SetWindowFullscreen(d->base.win, SDL_WINDOW_FULLSCREEN_DESKTOP);[m break;[m }[m if (snapMode & (topBit_WindowSnap | bottomBit_WindowSnap)) {[m [36m@@ -1425,9 +1458,9 @@[m [mvoid setSnap_Window(iWindow *d, int snapMode) {[m #endif /* defined (LAGRANGE_ENABLE_CUSTOM_FRAME) */[m }[m [m [31m-int snap_Window(const iWindow *d) {[m [32m+[m[32mint snap_MainWindow(const iMainWindow *d) {[m if (!prefs_App()->customFrame) {[m [31m- const int flags = SDL_GetWindowFlags(d->win);[m [32m+[m[32m const int flags = SDL_GetWindowFlags(d->base.win);[m if (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) {[m return fullscreen_WindowSnap;[m }[m [1mdiff --git a/src/ui/window.h b/src/ui/window.h[m [1mindex 282e1682..73e92391 100644[m [1m--- a/src/ui/window.h[m [1m+++ b/src/ui/window.h[m [36m@@ -29,8 +29,11 @@[m [mSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */[m #include[m #include [m [m [32m+[m[32miDeclareType(MainWindow)[m iDeclareType(Window)[m [31m-iDeclareTypeConstructionArgs(Window, iRect rect)[m [32m+[m[32miDeclareTypeConstructionArgs(MainWindow, iRect rect)[m [32m+[m[41m [m [32m+[m[32mtypedef iAny iAnyWindow;[m [m enum iWindowSnap {[m none_WindowSnap = 0,[m [36m@@ -68,9 +71,14 @@[m [menum iWindowSplit {[m noEvents_WindowSplit = iBit(11),[m };[m [m [32m+[m[32menum iWindowType {[m [32m+[m[32m main_WindowType,[m [32m+[m[32m popup_WindowType,[m [32m+[m[32m};[m [32m+[m struct Impl_Window {[m [32m+[m[32m enum iWindowType type;[m SDL_Window * win;[m [31m- iWindowPlacement place;[m iBool isDrawFrozen; /* avoids premature draws while restoring window state */[m iBool isExposed;[m iBool isMinimized;[m [36m@@ -80,11 +88,6 @@[m [mstruct Impl_Window {[m uint32_t focusGainedAt;[m SDL_Renderer *render;[m iInt2 size;[m [31m- int splitMode;[m [31m- int pendingSplitMode;[m [31m- iString * pendingSplitUrl; /* URL to open in a newly opened split */[m [31m- iRoot * roots[2]; /* root widget and UI state; second one is for split mode */[m [31m- iRoot * keyRoot; /* root that has the current keyboard input focus */[m iWidget * hover;[m iWidget * lastHover; /* cleared if deleted */[m iWidget * mouseGrab;[m [36m@@ -94,56 +97,102 @@[m [mstruct Impl_Window {[m float uiScale;[m uint32_t frameTime;[m double presentTime;[m [31m- SDL_Texture * appIcon;[m [31m- SDL_Texture * borderShadow;[m SDL_Cursor * cursors[SDL_NUM_SYSTEM_CURSORS];[m SDL_Cursor * pendingCursor;[m [31m- int loadAnimTimer;[m [31m- int keyboardHeight; /* mobile software keyboards */[m [32m+[m[32m iRoot * roots[2]; /* root widget and UI state; second one is for split mode */[m [32m+[m[32m iRoot * keyRoot; /* root that has the current keyboard input focus */[m [32m+[m[32m SDL_Texture * borderShadow;[m [32m+[m[32m};[m [32m+[m [32m+[m[32mstruct Impl_MainWindow {[m [32m+[m[32m iWindow base;[m [32m+[m[32m iWindowPlacement place;[m [32m+[m[32m int splitMode;[m [32m+[m[32m int pendingSplitMode;[m [32m+[m[32m iString * pendingSplitUrl; /* URL to open in a newly opened split */[m [32m+[m[32m SDL_Texture * appIcon;[m [32m+[m[32m int keyboardHeight; /* mobile software keyboards */[m[41m [m };[m [m [31m-iBool processEvent_Window (iWindow *, const SDL_Event *);[m [32m+[m[32miLocalDef enum iWindowType type_Window(const iAnyWindow *d) {[m [32m+[m[32m return ((const iWindow *) d)->type;[m [32m+[m[32m}[m [32m+[m [32m+[m[32muint32_t id_Window (const iWindow *);[m [32m+[m[32miInt2 size_Window (const iWindow *);[m [32m+[m[32miInt2 maxTextureSize_Window (const iWindow *);[m [32m+[m[32mfloat uiScale_Window (const iWindow *);[m [32m+[m[32miInt2 coord_Window (const iWindow *, int x, int y);[m [32m+[m[32miInt2 mouseCoord_Window (const iWindow *, int whichDevice);[m [32m+[m[32miAnyObject * hitChild_Window (const iWindow *, iInt2 coord);[m [32m+[m[32muint32_t frameTime_Window (const iWindow *);[m [32m+[m[32mSDL_Renderer * renderer_Window (const iWindow *);[m [32m+[m[32mint numRoots_Window (const iWindow *);[m [32m+[m[32miRoot * findRoot_Window (const iWindow *, const iWidget *widget);[m [32m+[m[32miRoot * otherRoot_Window (const iWindow *, iRoot *root);[m [32m+[m iBool dispatchEvent_Window (iWindow *, const SDL_Event *);[m [31m-void invalidate_Window (iWindow *); /* discard all cached graphics */[m [32m+[m[32mvoid invalidate_Window (iAnyWindow *); /* discard all cached graphics */[m void draw_Window (iWindow *);[m [31m-void drawWhileResizing_Window(iWindow *d, int w, int h); /* workaround for SDL bug */[m [31m-void resize_Window (iWindow *, int w, int h);[m [31m-void setTitle_Window (iWindow *, const iString *title);[m void setUiScale_Window (iWindow *, float uiScale);[m void setFreezeDraw_Window (iWindow *, iBool freezeDraw);[m [31m-iBool setKeyRoot_Window (iWindow *, iRoot *root);[m void setCursor_Window (iWindow *, int cursor);[m [31m-void setSnap_Window (iWindow *, int snapMode);[m [31m-void setKeyboardHeight_Window(iWindow *, int height);[m [31m-void setSplitMode_Window (iWindow *, int splitMode);[m [31m-void showToolbars_Window (iWindow *, iBool show);[m [32m+[m[32miBool setKeyRoot_Window (iWindow *, iRoot *root);[m iBool postContextClick_Window (iWindow *, const SDL_MouseButtonEvent *);[m [31m-void checkPendingSplit_Window(iWindow *);[m [31m-void swapRoots_Window (iWindow *);[m [31m-[m [31m-uint32_t id_Window (const iWindow *);[m [31m-iInt2 size_Window (const iWindow *);[m [31m-iInt2 maxTextureSize_Window (const iWindow *);[m [31m-float uiScale_Window (const iWindow *);[m [31m-iInt2 coord_Window (const iWindow *, int x, int y);[m [31m-iInt2 mouseCoord_Window (const iWindow *, int whichDevice);[m [31m-iAnyObject *hitChild_Window (const iWindow *, iInt2 coord);[m [31m-uint32_t frameTime_Window (const iWindow *);[m [31m-SDL_Renderer *renderer_Window (const iWindow *);[m [31m-int snap_Window (const iWindow *);[m [31m-iBool isFullscreen_Window (const iWindow *);[m [31m-int numRoots_Window (const iWindow *);[m [31m-iRoot * findRoot_Window (const iWindow *, const iWidget *widget);[m [31m-iRoot * otherRoot_Window (const iWindow *, iRoot *root);[m [31m-iWindow * get_Window (void);[m [m [32m+[m[32miWindow * get_Window (void);[m iBool isOpenGLRenderer_Window (void);[m [m [31m-#if defined (LAGRANGE_ENABLE_CUSTOM_FRAME)[m [31m-SDL_HitTestResult hitTest_Window(const iWindow *d, iInt2 pos);[m [31m-#endif[m [31m-[m iLocalDef iBool isExposed_Window(const iWindow *d) {[m iAssert(d);[m return d->isExposed;[m }[m [32m+[m [32m+[m[32miLocalDef iWindow *as_Window(iAnyWindow *d) {[m [32m+[m[32m iAssert(type_Window(d) == main_WindowType || type_Window(d) == popup_WindowType);[m [32m+[m[32m return (iWindow *) d;[m [32m+[m[32m}[m [32m+[m [32m+[m[32miLocalDef const iWindow *constAs_Window(const iAnyWindow *d) {[m [32m+[m[32m iAssert(type_Window(d) == main_WindowType || type_Window(d) == popup_WindowType);[m [32m+[m[32m return (const iWindow *) d;[m [32m+[m[32m}[m [32m+[m [32m+[m[32m/*----------------------------------------------------------------------------------------------*/[m [32m+[m [32m+[m[32miLocalDef iWindow *asWindow_MainWindow(iMainWindow *d) {[m [32m+[m[32m iAssert(type_Window(d) == main_WindowType);[m [32m+[m[32m return &d->base;[m [32m+[m[32m}[m [32m+[m [32m+[m[32mvoid setTitle_MainWindow (iMainWindow *, const iString *title);[m [32m+[m[32mvoid setSnap_MainWindow (iMainWindow *, int snapMode);[m [32m+[m[32mvoid setKeyboardHeight_MainWindow (iMainWindow *, int height);[m [32m+[m[32mvoid setSplitMode_MainWindow (iMainWindow *, int splitMode);[m [32m+[m[32mvoid checkPendingSplit_MainWindow (iMainWindow *);[m [32m+[m[32mvoid swapRoots_MainWindow (iMainWindow *);[m [32m+[m[32mvoid showToolbars_MainWindow (iMainWindow *, iBool show);[m [32m+[m[32mvoid resize_MainWindow (iMainWindow *, int w, int h);[m [32m+[m [32m+[m[32miBool processEvent_MainWindow (iMainWindow *, const SDL_Event *);[m [32m+[m[32mvoid draw_MainWindow (iMainWindow *);[m [32m+[m[32mvoid drawWhileResizing_MainWindow (iMainWindow *, int w, int h); /* workaround for SDL bug */[m [32m+[m [32m+[m[32mint snap_MainWindow (const iMainWindow *);[m [32m+[m[32miBool isFullscreen_Window (const iMainWindow *);[m [32m+[m [32m+[m[32m#if defined (LAGRANGE_ENABLE_CUSTOM_FRAME)[m [32m+[m[32mSDL_HitTestResult hitTest_MainWindow(const iMainWindow *d, iInt2 pos);[m [32m+[m[32m#endif[m [32m+[m [32m+[m[32miMainWindow * get_MainWindow (void);[m [32m+[m [32m+[m[32miLocalDef iMainWindow *as_MainWindow(iAnyWindow *d) {[m [32m+[m[32m iAssert(type_Window(d) == main_WindowType);[m [32m+[m[32m return (iMainWindow *) d;[m [32m+[m[32m}[m [32m+[m [32m+[m[32miLocalDef const iMainWindow *constAs_MainWindow(const iAnyWindow *d) {[m [32m+[m[32m iAssert(type_Window(d) == main_WindowType);[m [32m+[m[32m return (const iMainWindow *) d;[m [32m+[m[32m}[m
text/gemini; charset=utf-8
This content has been proxied by September (ba2dc).