Lagrange [work/v1.13]

Reopening the last closed tab

=> b854a7677bb1f72b77f9d8fcbbc481f368949680

diff --git a/po/en.po b/po/en.po
index e9bdd590..37777559 100644
--- a/po/en.po
+++ b/po/en.po
@@ -154,6 +154,9 @@ msgstr "New Window"
 msgid "menu.newtab"
 msgstr "New Tab"
 
+msgid "menu.reopentab"
+msgstr "Reopen Last Closed Tab"
+
 msgid "menu.closetab"
 msgstr "Close Tab"
 
diff --git a/src/app.c b/src/app.c
index 89c60698..4055916a 100644
--- a/src/app.c
+++ b/src/app.c
@@ -134,6 +134,7 @@ struct Impl_App {
     iCommandLine args;
     iString *    execPath;
     iStringSet * tempFilesPendingDeletion;
+    iStringList *recentlyClosedTabUrls; /* for reopening, like an undo stack */
     iMimeHooks * mimehooks;
     iGmCerts *   certs;
     iVisited *   visited;
@@ -168,7 +169,6 @@ struct Impl_App {
     /* Preferences: */
     iBool        commandEcho;         /* --echo */
     iBool        forceSoftwareRender; /* --sw */
-    //iRect        initialWindowRect;
     iArray       initialWindowRects; /* one per window */
     iPrefs       prefs;
 };
@@ -907,7 +907,8 @@ static void init_App_(iApp *d, int argc, char **argv) {
     d->isDarkSystemTheme = iTrue; /* will be updated by system later on, if supported */
     d->isSuspended = iFalse;
     d->tempFilesPendingDeletion = new_StringSet();
-    init_Array(&d->initialWindowRects, sizeof(iRect));
+    d->recentlyClosedTabUrls = new_StringList();
+    init_Array(&d->initialWindowRects, sizeof(iRect));    
     init_CommandLine(&d->args, argc, argv);
     /* Where was the app started from? We ask SDL first because the command line alone
        cannot be relied on (behavior differs depending on OS). */ {
@@ -1211,6 +1212,7 @@ static void deinit_App(iApp *d) {
         remove(cstr_String(tmp.value));
     }
     deinit_Array(&d->initialWindowRects);
+    iRelease(d->recentlyClosedTabUrls);
     iRelease(d->tempFilesPendingDeletion);
 }
 
@@ -2616,6 +2618,20 @@ static void invalidateCachedDocuments_App_(void) {
     }
 }
 
+static void pushClosedTabUrl_App_(iApp *d, const iString *url) {
+    pushBack_StringList(d->recentlyClosedTabUrls, url);
+    if (size_StringList(d->recentlyClosedTabUrls) > 50) { /* not an infinite number */
+        popFront_StringList(d->recentlyClosedTabUrls);
+    }
+}
+
+static const iString *popClosedTabUrl_App_(iApp *d) {
+    if (isEmpty_StringList(d->recentlyClosedTabUrls)) {
+        return NULL;
+    }
+    return collect_String(takeLast_StringList(d->recentlyClosedTabUrls));    
+}
+
 static iBool handleNonWindowRelatedCommand_App_(iApp *d, const char *cmd) {
     const iBool isFrozen = !d->window || d->window->isDrawFrozen;
     /* Commands related to preferences. */
@@ -3524,8 +3540,16 @@ iBool handleCommand_App(const char *cmd) {
         return iFalse;
     }
     else if (equal_Command(cmd, "tabs.new")) {
+        if (argLabel_Command(cmd, "reopen")) {
+            const iString *reopenUrl = popClosedTabUrl_App_(d);
+            if (reopenUrl) {
+                newTab_App(NULL, iTrue);
+                postCommandf_App("open url:%s", cstr_String(reopenUrl));
+            }
+            return iTrue;
+        }
         const iBool isDuplicate = argLabel_Command(cmd, "duplicate") != 0;
-        newTab_App(isDuplicate ? document_App() : NULL, iTrue);
+        newTab_App(isDuplicate ? document_App() : NULL, iTrue);        
         if (!isDuplicate) {
             postCommandf_App("navigate.home focus:%d", deviceType_App() == desktop_AppDeviceType);
         }
@@ -3549,13 +3573,19 @@ iBool handleCommand_App(const char *cmd) {
         postCommand_App("document.openurls.changed");
         if (argLabel_Command(cmd, "toright")) {
             while (tabCount_Widget(tabs) > index + 1) {
-                destroy_Widget(removeTabPage_Widget(tabs, index + 1));
+                iDocumentWidget *closed = (iDocumentWidget *) removeTabPage_Widget(tabs, index + 1);
+                pushClosedTabUrl_App_(d, url_DocumentWidget(closed));
+                cancelAllRequests_DocumentWidget(closed);
+                destroy_Widget(as_Widget(closed));
             }
             wasClosed = iTrue;
         }
         if (argLabel_Command(cmd, "toleft")) {
             while (index-- > 0) {
-                destroy_Widget(removeTabPage_Widget(tabs, 0));
+                iDocumentWidget *closed = (iDocumentWidget *) removeTabPage_Widget(tabs, 0);
+                pushClosedTabUrl_App_(d, url_DocumentWidget(closed));
+                cancelAllRequests_DocumentWidget(closed);
+                destroy_Widget(as_Widget(closed));
             }
             postCommandf_App("tabs.switch page:%p", tabPage_Widget(tabs, 0));
             wasClosed = iTrue;
@@ -3566,9 +3596,10 @@ iBool handleCommand_App(const char *cmd) {
         }
         const iBool isSplit = numRoots_Window(get_Window()) > 1;
         if (tabCount_Widget(tabs) > 1 || isSplit) {
-            iWidget *closed = removeTabPage_Widget(tabs, index);
-            cancelAllRequests_DocumentWidget((iDocumentWidget *) closed);
-            destroy_Widget(closed); /* released later */
+            iDocumentWidget *closed = (iDocumentWidget *) removeTabPage_Widget(tabs, index);
+            pushClosedTabUrl_App_(d, url_DocumentWidget(closed));
+            cancelAllRequests_DocumentWidget(closed);
+            destroy_Widget(as_Widget(closed)); /* released later */
             if (index == tabCount_Widget(tabs)) {
                 index--;
             }
diff --git a/src/app.h b/src/app.h
index 60421e2b..98d49fbb 100644
--- a/src/app.h
+++ b/src/app.h
@@ -126,6 +126,7 @@ 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);
@@ -134,8 +135,11 @@ size_t      numWindows_App      (void);
 size_t      windowIndex_App     (const iMainWindow *win);
 iMainWindow *newMainWindow_App  (void);
 const iPtrArray *mainWindows_App(void);
+iMainWindow *    mainWindow_App (void); /* currently active main window */
 void        addPopup_App        (iWindow *popup);
 void        removePopup_App     (iWindow *popup);
+void        closePopups_App     (iBool doForce);
+
 void        postRefresh_App     (void);
 void        postCommand_Root    (iRoot *, const char *command);
 void        postCommandf_Root   (iRoot *, const char *command, ...);
@@ -156,6 +160,3 @@ void            openInDefaultBrowser_App(const iString *url);
 void            revealPath_App          (const iString *path);
 void            resetFonts_App          (void);
 void            availableFontsChanged_App(void);
-
-iMainWindow *   mainWindow_App  (void);
-void            closePopups_App (iBool doForce);
diff --git a/src/ui/keys.c b/src/ui/keys.c
index 6a12b5e7..c3b68316 100644
--- a/src/ui/keys.c
+++ b/src/ui/keys.c
@@ -227,7 +227,8 @@ static const struct { int id; iMenuItem bind; int flags; } defaultBindings_[] =
 #endif
     { 76, { "${keys.tab.new}",              newTab_KeyShortcut,             "tabs.new"                          }, 0 },
     { 77, { "${keys.tab.close}",            closeTab_KeyShortcut,           "tabs.close"                        }, 0 },
-    { 78, { "${keys.tab.close.other}",      SDLK_w, KMOD_SECONDARY, "tabs.close toleft:1 toright:1"  }, 0 },
+    { 78, { "${keys.tab.close.other}",      SDLK_w, KMOD_SECONDARY,         "tabs.close toleft:1 toright:1"     }, 0 },
+    { 79, { "${LC:menu.reopentab}",         SDLK_t, KMOD_SECONDARY,         "tabs.new reopen:1"                 }, 0 },        
     { 80, { "${keys.tab.prev}",             prevTab_KeyShortcut,            "tabs.prev"                         }, 0 },
     { 81, { "${keys.tab.next}",             nextTab_KeyShortcut,            "tabs.next"                         }, 0 },
     { 90, { "${keys.split.menu}",           SDLK_j, KMOD_PRIMARY,           "splitmenu.open"                    }, 0 },
diff --git a/src/ui/window.c b/src/ui/window.c
index 0d1923c6..c773bc96 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -73,6 +73,7 @@ iDefineTypeConstructionArgs(MainWindow, (iRect rect), rect)
 static const iMenuItem fileMenuItems_[] = {
     { "${menu.newwindow}", SDLK_n, KMOD_PRIMARY, "window.new" },
     { "${menu.newtab}", SDLK_t, KMOD_PRIMARY, "tabs.new" },
+    { "${menu.reopentab}", SDLK_t, KMOD_SECONDARY, "tabs.new reopen:1" },
     { "${menu.openlocation}", SDLK_l, KMOD_PRIMARY, "navigate.focus" },
     { "---" },
     { saveToDownloads_Label, SDLK_s, KMOD_PRIMARY, "document.save" },
Proxy Information
Original URL
gemini://git.skyjake.fi/lagrange/work%2Fv1.13/cdiff/b854a7677bb1f72b77f9d8fcbbc481f368949680
Status Code
Success (20)
Meta
text/gemini; charset=utf-8
Capsule Response Time
107.981831 milliseconds
Gemini-to-HTML Time
0.314332 milliseconds

This content has been proxied by September (ba2dc).