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