Lagrange [work/v1.11]

Basic opening and closing of new windows

=> bef61b34d8a23e2e8594207c2876ce982fe0e15f

diff --git a/src/app.c b/src/app.c
index d47c6ef1..686d8b82 100644
--- a/src/app.c
+++ b/src/app.c
@@ -125,7 +125,8 @@ struct Impl_App {
     iGmCerts *   certs;
     iVisited *   visited;
     iBookmarks * bookmarks;
-    iMainWindow *window;
+    iMainWindow *window; /* currently active MainWindow */
+    iPtrArray    mainWindows;
     iPtrArray    popupWindows;
     iSortedArray tickers; /* per-frame callbacks, used for animations */
     uint32_t     lastTickerTime;
@@ -474,7 +475,7 @@ static const char *magicTabDocument_App_ = "tabd";
 static const char *magicSidebar_App_     = "side";
 
 enum iDocumentStateFlag {
-    current_DocumentStateFlag     = iBit(1),
+    current_DocumentStateFlag    = iBit(1),
     rootIndex1_DocumentStateFlag = iBit(2)
 };
 
@@ -946,8 +947,10 @@ static void init_App_(iApp *d, int argc, char **argv) {
             d->initialWindowRect.size.y = toInt_String(value_CommandLineArg(arg, 0));
         }
     }
+    init_PtrArray(&d->mainWindows);
     init_PtrArray(&d->popupWindows);
     d->window = new_MainWindow(d->initialWindowRect);
+    addWindow_App(d->window);
     load_Visited(d->visited, dataDir_App_());
     load_Bookmarks(d->bookmarks, dataDir_App_());
     load_MimeHooks(d->mimehooks, dataDir_App_());
@@ -1012,7 +1015,11 @@ static void deinit_App(iApp *d) {
     SDL_RemoveTimer(d->autoReloadTimer);
     saveState_App_(d);
     savePrefs_App_(d);
-    delete_MainWindow(d->window);
+    iReverseForEach(PtrArray, j, &d->mainWindows) {
+        delete_MainWindow(j.ptr);
+    }
+    iAssert(isEmpty_PtrArray(&d->mainWindows));
+    deinit_PtrArray(&d->mainWindows);
     d->window = NULL;
     deinit_Feeds();
     save_Keys(dataDir_App_());
@@ -1027,7 +1034,6 @@ static void deinit_App(iApp *d) {
     delete_GmCerts(d->certs);
     save_MimeHooks(d->mimehooks);
     delete_MimeHooks(d->mimehooks);
-    d->window = NULL;
     deinit_CommandLine(&d->args);
     iRelease(d->launchCommands);
     delete_String(d->execPath);
@@ -1286,7 +1292,14 @@ static iPtrArray *listWindows_App_(const iApp *d, iPtrArray *windows) {
     iReverseConstForEach(PtrArray, i, &d->popupWindows) {
         pushBack_PtrArray(windows, i.ptr);
     }
-    pushBack_PtrArray(windows, d->window);
+    if (d->window) {
+        pushBack_PtrArray(windows, d->window);
+    }
+    iConstForEach(PtrArray, j, &d->mainWindows) {
+        if (j.ptr != d->window) {
+            pushBack_PtrArray(windows, j.ptr);
+        }
+    }
     return windows;
 }
 
@@ -1843,6 +1856,26 @@ void removeTicker_App(iTickerFunc ticker, iAny *context) {
     remove_SortedArray(&d->tickers, &(iTicker){ context, NULL, ticker });
 }
 
+void addWindow_App(iMainWindow *win) {
+    iApp *d = &app_;
+    pushBack_PtrArray(&d->mainWindows, win);
+}
+
+void removeWindow_App(iMainWindow *win) {
+    iApp *d = &app_;
+    removeOne_PtrArray(&d->mainWindows, win);
+}
+
+size_t numWindows_App(void) {
+    return size_PtrArray(&app_.mainWindows);
+}
+
+void setActiveWindow_App(iMainWindow *win) {
+    iApp *d = &app_;
+    d->window = win;
+    printf("Active window: %p\n", win); fflush(stdout);
+}
+
 void addPopup_App(iWindow *popup) {
     iApp *d = &app_;
     pushBack_PtrArray(&d->popupWindows, popup);
@@ -2121,6 +2154,22 @@ iDocumentWidget *newTab_App(const iDocumentWidget *duplicateOf, iBool switchToNe
     return doc;
 }
 
+void closeWindow_App(iMainWindow *win) {
+    iApp *d = &app_;
+    delete_MainWindow(win);
+    if (d->window == win) {
+        /* Activate another window. */
+        iForEach(PtrArray, i, &d->mainWindows) {
+            if (i.ptr != d->window) {
+                SDL_RaiseWindow(i.ptr);
+                setActiveWindow_App(i.ptr);
+                setCurrent_Window(i.ptr);
+                break;
+            }
+        }
+    }
+}
+
 static iBool handleIdentityCreationCommands_(iWidget *dlg, const char *cmd) {
     iApp *d = &app_;
     if (equal_Command(cmd, "ident.showmore")) {
@@ -3016,6 +3065,15 @@ iBool handleCommand_App(const char *cmd) {
 #endif
         return iFalse;
     }
+    else if (equal_Command(cmd, "window.new")) {
+        iMainWindow *newWin = new_MainWindow(moved_Rect(d->initialWindowRect, init_I2(20, 20)));
+        addWindow_App(newWin);
+        SDL_ShowWindow(newWin->base.win);
+        setCurrent_Window(newWin);
+        postCommand_Root(newWin->base.roots[0], "navigate.home");
+        postCommand_Root(newWin->base.roots[0], "window.unfreeze");
+        return iTrue;
+    }
     else if (equal_Command(cmd, "tabs.new")) {
         const iBool isDuplicate = argLabel_Command(cmd, "duplicate") != 0;
         newTab_App(isDuplicate ? document_App() : NULL, iTrue);
@@ -3076,6 +3134,9 @@ iBool handleCommand_App(const char *cmd) {
                 }
             }
         }
+        else if (numWindows_App() > 1) {
+            closeWindow_App(d->window);
+        }
         else {
             postCommand_App("quit");
         }
diff --git a/src/app.h b/src/app.h
index 22fe5d46..74a5429b 100644
--- a/src/app.h
+++ b/src/app.h
@@ -122,6 +122,11 @@ iAny *      findWidget_App      (const char *id);
 void        addTicker_App       (iTickerFunc ticker, iAny *context);
 void        addTickerRoot_App   (iTickerFunc ticker, iRoot *root, iAny *context);
 void        removeTicker_App    (iTickerFunc ticker, iAny *context);
+void        addWindow_App       (iMainWindow *win);
+void        removeWindow_App    (iMainWindow *win);
+void        setActiveWindow_App (iMainWindow *win);
+void        closeWindow_App     (iMainWindow *win);
+size_t      numWindows_App      (void);
 void        addPopup_App        (iWindow *popup);
 void        removePopup_App     (iWindow *popup);
 void        postRefresh_App     (void);
diff --git a/src/ui/window.c b/src/ui/window.c
index 47abf878..bc32e479 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -80,6 +80,7 @@ iDefineTypeConstructionArgs(MainWindow, (iRect rect), rect)
 #if defined (iHaveNativeMenus)
 /* Using native menus. */
 static const iMenuItem fileMenuItems_[] = {
+    { "${menu.newwindow}", SDLK_n, KMOD_PRIMARY, "window.new" },
     { "${menu.newtab}", SDLK_t, KMOD_PRIMARY, "tabs.new" },
     { "${menu.openlocation}", SDLK_l, KMOD_PRIMARY, "navigate.focus" },
     { "---", 0, 0, NULL },
@@ -210,7 +211,9 @@ static void windowSizeChanged_MainWindow_(iMainWindow *d) {
 
 static void setupUserInterface_MainWindow(iMainWindow *d) {
 #if defined (iHaveNativeMenus)
-    insertMacMenus_();
+    if (numWindows_App() == 0) {
+        insertMacMenus_(); /* TODO: Shouldn't this be in the App? */
+    }
 #endif
     /* One root is created by default. */
     d->base.roots[0] = new_Root();
@@ -246,6 +249,7 @@ static void updateSize_MainWindow_(iMainWindow *d, iBool notifyAlways) {
 
 void drawWhileResizing_MainWindow(iMainWindow *d, int w, int h) {
     if (!isDrawing_) {
+        setCurrent_Window(d);
         draw_MainWindow(d);
     }
 }
@@ -647,6 +651,7 @@ void init_MainWindow(iMainWindow *d, iRect rect) {
 }
 
 void deinit_MainWindow(iMainWindow *d) {
+    removeWindow_App(d);
     if (d->backBuf) {
         SDL_DestroyTexture(d->backBuf);
     }
@@ -830,6 +835,9 @@ static void savePlace_MainWindow_(iAny *mainWindow) {
 }
 
 static iBool handleWindowEvent_MainWindow_(iMainWindow *d, const SDL_WindowEvent *ev) {
+    if (ev->windowID != SDL_GetWindowID(d->base.win)) {
+        return iFalse;
+    }
     switch (ev->event) {
 #if defined(iPlatformDesktop)
         case SDL_WINDOWEVENT_EXPOSED:
@@ -953,6 +961,7 @@ static iBool handleWindowEvent_MainWindow_(iMainWindow *d, const SDL_WindowEvent
             setCapsLockDown_Keys(iFalse);
             postCommand_App("window.focus.gained");
             d->base.isExposed = iTrue;
+            setActiveWindow_App(d);
 #if !defined (iPlatformDesktop)
             /* Returned to foreground, may have lost buffered content. */
             invalidate_MainWindow_(d, iTrue);
@@ -970,6 +979,11 @@ static iBool handleWindowEvent_MainWindow_(iMainWindow *d, const SDL_WindowEvent
             SDL_SetWindowInputFocus(d->base.win);
             postRefresh_App();
             return iTrue;
+        case SDL_WINDOWEVENT_CLOSE:
+            if (numWindows_App() > 1) {
+                closeWindow_App(d);
+            }
+            return iTrue;
         default:
             break;
     }
Proxy Information
Original URL
gemini://git.skyjake.fi/lagrange/work%2Fv1.11/cdiff/bef61b34d8a23e2e8594207c2876ce982fe0e15f
Status Code
Success (20)
Meta
text/gemini; charset=utf-8
Capsule Response Time
27.034192 milliseconds
Gemini-to-HTML Time
0.43334 milliseconds

This content has been proxied by September (ba2dc).