summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--po/en.po12
-rw-r--r--src/app.c45
-rw-r--r--src/app.h1
-rw-r--r--src/defs.h5
-rw-r--r--src/gmutil.c11
-rw-r--r--src/gmutil.h2
-rw-r--r--src/ui/documentwidget.c68
-rw-r--r--src/ui/lookupwidget.c2
-rw-r--r--src/ui/root.c3
-rw-r--r--src/ui/sidebarwidget.c28
-rw-r--r--src/ui/window.c17
-rw-r--r--src/ui/window.h1
12 files changed, 128 insertions, 67 deletions
diff --git a/po/en.po b/po/en.po
index bff4c495..6647324e 100644
--- a/po/en.po
+++ b/po/en.po
@@ -148,6 +148,9 @@ msgstr "Identity"
148msgid "menu.title.help" 148msgid "menu.title.help"
149msgstr "Help" 149msgstr "Help"
150 150
151msgid "menu.newwindow"
152msgstr "New Window"
153
151msgid "menu.newtab" 154msgid "menu.newtab"
152msgstr "New Tab" 155msgstr "New Tab"
153 156
@@ -519,9 +522,6 @@ msgstr "%b. %d, %Y"
519msgid "feeds.today" 522msgid "feeds.today"
520msgstr "Today" 523msgstr "Today"
521 524
522msgid "feeds.entry.newtab"
523msgstr "Open Entry in New Tab"
524
525msgid "feeds.entry.markread" 525msgid "feeds.entry.markread"
526msgstr "Mark as Read" 526msgstr "Mark as Read"
527 527
@@ -558,6 +558,9 @@ msgstr "Open in New Tab"
558msgid "menu.opentab.background" 558msgid "menu.opentab.background"
559msgstr "Open in Background Tab" 559msgstr "Open in Background Tab"
560 560
561msgid "menu.openwindow"
562msgstr "Open in New Window"
563
561msgid "menu.openfile" 564msgid "menu.openfile"
562msgstr "Open File…" 565msgstr "Open File…"
563 566
@@ -870,6 +873,9 @@ msgstr "Open Link to the Side"
870msgid "link.side.newtab" 873msgid "link.side.newtab"
871msgstr "Open Link in New Tab to the Side" 874msgstr "Open Link in New Tab to the Side"
872 875
876msgid "link.newwindow"
877msgstr "Open Link in New Window"
878
873msgid "link.browser" 879msgid "link.browser"
874msgstr "Open Link in Default Browser" 880msgstr "Open Link in Default Browser"
875 881
diff --git a/src/app.c b/src/app.c
index 010c6d74..543467ef 100644
--- a/src/app.c
+++ b/src/app.c
@@ -1878,7 +1878,7 @@ void postCommand_Root(iRoot *d, const char *command) {
1878 ev.user.data2 = d; /* all events are root-specific */ 1878 ev.user.data2 = d; /* all events are root-specific */
1879 ev.user.windowID = d ? id_Window(d->window) : 0; /* root-specific means window-specific */ 1879 ev.user.windowID = d ? id_Window(d->window) : 0; /* root-specific means window-specific */
1880 SDL_PushEvent(&ev); 1880 SDL_PushEvent(&ev);
1881 iWindow *win = get_Window(); 1881 iWindow *win = d ? d->window : NULL;
1882#if defined (iPlatformAndroid) 1882#if defined (iPlatformAndroid)
1883 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "%s[command] {%d} %s", 1883 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "%s[command] {%d} %s",
1884 app_.isLoadingPrefs ? "[Prefs] " : "", 1884 app_.isLoadingPrefs ? "[Prefs] " : "",
@@ -1979,6 +1979,13 @@ size_t windowIndex_App(const iMainWindow *win) {
1979 return indexOf_PtrArray(&app_.mainWindows, win); 1979 return indexOf_PtrArray(&app_.mainWindows, win);
1980} 1980}
1981 1981
1982iMainWindow *newMainWindow_App(void) {
1983 iApp *d = &app_;
1984 iMainWindow *win = new_MainWindow(initialWindowRect_App_(d, size_PtrArray(&d->mainWindows)));
1985 addWindow_App(win);
1986 return win;
1987}
1988
1982const iPtrArray *mainWindows_App(void) { 1989const iPtrArray *mainWindows_App(void) {
1983 return &app_.mainWindows; 1990 return &app_.mainWindows;
1984} 1991}
@@ -3038,7 +3045,18 @@ iBool handleCommand_App(const char *cmd) {
3038 return iTrue; /* invalid command */ 3045 return iTrue; /* invalid command */
3039 } 3046 }
3040 if (findWidget_App("prefs")) { 3047 if (findWidget_App("prefs")) {
3041 postCommand_App("prefs.dismiss"); 3048 postCommand_App("prefs.dismiss");
3049 }
3050 if (argLabel_Command(cmd, "newwindow")) {
3051 const iRangecc gotoheading = range_Command(cmd, "gotoheading");
3052 const iRangecc gotourlheading = range_Command(cmd, "gotourlheading");
3053 postCommandf_Root(get_Root(), "window.new%s%s%s%s url:%s",
3054 isEmpty_Range(&gotoheading) ? "" : " gotoheading:",
3055 isEmpty_Range(&gotoheading) ? "" : cstr_Rangecc(gotoheading),
3056 isEmpty_Range(&gotourlheading) ? "" : " gotourlheading:",
3057 isEmpty_Range(&gotourlheading) ? "" : cstr_Rangecc(gotourlheading),
3058 urlArg);
3059 return iTrue;
3042 } 3060 }
3043 iString *url = collectNewCStr_String(urlArg); 3061 iString *url = collectNewCStr_String(urlArg);
3044 const iBool noProxy = argLabel_Command(cmd, "noproxy") != 0; 3062 const iBool noProxy = argLabel_Command(cmd, "noproxy") != 0;
@@ -3187,7 +3205,12 @@ iBool handleCommand_App(const char *cmd) {
3187 addWindow_App(newWin); /* takes ownership */ 3205 addWindow_App(newWin); /* takes ownership */
3188 SDL_ShowWindow(newWin->base.win); 3206 SDL_ShowWindow(newWin->base.win);
3189 setCurrent_Window(newWin); 3207 setCurrent_Window(newWin);
3190 postCommand_Root(newWin->base.roots[0], "~navigate.home"); 3208 if (hasLabel_Command(cmd, "url")) {
3209 postCommandf_Root(newWin->base.roots[0], "~open %s", cmd + 11 /* all arguments passed on */);
3210 }
3211 else {
3212 postCommand_Root(newWin->base.roots[0], "~navigate.home");
3213 }
3191 postCommand_Root(newWin->base.roots[0], "~window.unfreeze"); 3214 postCommand_Root(newWin->base.roots[0], "~window.unfreeze");
3192 return iTrue; 3215 return iTrue;
3193 } 3216 }
@@ -3745,21 +3768,7 @@ void revealPath_App(const iString *path) {
3745} 3768}
3746 3769
3747iObjectList *listDocuments_App(const iRoot *rootOrNull) { 3770iObjectList *listDocuments_App(const iRoot *rootOrNull) {
3748 iWindow *win = get_Window(); 3771 return listDocuments_MainWindow(get_MainWindow(), rootOrNull);
3749 iObjectList *docs = new_ObjectList();
3750 iForIndices(i, win->roots) {
3751 iRoot *root = win->roots[i];
3752 if (!root) continue;
3753 if (!rootOrNull || root == rootOrNull) {
3754 const iWidget *tabs = findChild_Widget(root->widget, "doctabs");
3755 iForEach(ObjectList, i, children_Widget(findChild_Widget(tabs, "tabs.pages"))) {
3756 if (isInstance_Object(i.object, &Class_DocumentWidget)) {
3757 pushBack_ObjectList(docs, i.object);
3758 }
3759 }
3760 }
3761 }
3762 return docs;
3763} 3772}
3764 3773
3765iStringSet *listOpenURLs_App(void) { 3774iStringSet *listOpenURLs_App(void) {
diff --git a/src/app.h b/src/app.h
index 63a477a5..5f7b506f 100644
--- a/src/app.h
+++ b/src/app.h
@@ -129,6 +129,7 @@ void setActiveWindow_App (iMainWindow *win);
129void closeWindow_App (iMainWindow *win); 129void closeWindow_App (iMainWindow *win);
130size_t numWindows_App (void); 130size_t numWindows_App (void);
131size_t windowIndex_App (const iMainWindow *win); 131size_t windowIndex_App (const iMainWindow *win);
132iMainWindow *newMainWindow_App (void);
132const iPtrArray *mainWindows_App(void); 133const iPtrArray *mainWindows_App(void);
133void addPopup_App (iWindow *popup); 134void addPopup_App (iWindow *popup);
134void removePopup_App (iWindow *popup); 135void removePopup_App (iWindow *popup);
diff --git a/src/defs.h b/src/defs.h
index be5280fa..c3480bc2 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -157,8 +157,9 @@ iLocalDef int acceptKeyMod_ReturnKeyBehavior(int behavior) {
157#define bookmark_Icon "\U0001f516" 157#define bookmark_Icon "\U0001f516"
158#define folder_Icon "\U0001f4c1" 158#define folder_Icon "\U0001f4c1"
159#define file_Icon "\U0001f5ce" 159#define file_Icon "\U0001f5ce"
160#define openTab_Icon "\u2750" 160#define openWindow_Icon "\u2b1a" //"\U0001F5d4"
161#define openTabBg_Icon "\u2b1a" 161#define openTab_Icon add_Icon
162#define openTabBg_Icon "\u2750" //"\u2b1a"
162#define openExt_Icon "\u27a0" 163#define openExt_Icon "\u27a0"
163#define add_Icon "\u2795" 164#define add_Icon "\u2795"
164#define page_Icon "\U00010117" 165#define page_Icon "\U00010117"
diff --git a/src/gmutil.c b/src/gmutil.c
index e862b18a..b32722ac 100644
--- a/src/gmutil.c
+++ b/src/gmutil.c
@@ -780,7 +780,7 @@ iRangecc mediaTypeWithoutParameters_Rangecc(iRangecc mime) {
780 return part; 780 return part;
781} 781}
782 782
783const iString *feedEntryOpenCommand_String(const iString *url, int newTab) { 783const iString *feedEntryOpenCommand_String(const iString *url, int newTab, int newWindow) {
784 if (!isEmpty_String(url)) { 784 if (!isEmpty_String(url)) {
785 iString *cmd = collectNew_String(); 785 iString *cmd = collectNew_String();
786 const size_t fragPos = indexOf_String(url, '#'); 786 const size_t fragPos = indexOf_String(url, '#');
@@ -788,15 +788,20 @@ const iString *feedEntryOpenCommand_String(const iString *url, int newTab) {
788 iString *head = newRange_String( 788 iString *head = newRange_String(
789 (iRangecc){ constBegin_String(url) + fragPos + 1, constEnd_String(url) }); 789 (iRangecc){ constBegin_String(url) + fragPos + 1, constEnd_String(url) });
790 format_String(cmd, 790 format_String(cmd,
791 "open fromsidebar:1 newtab:%d gotourlheading:%s url:%s", 791 "open fromsidebar:1 newtab:%d newwindow:%d gotourlheading:%s url:%s",
792 newTab, 792 newTab,
793 newWindow,
793 cstr_String(head), 794 cstr_String(head),
794 cstr_Rangecc((iRangecc){ constBegin_String(url), 795 cstr_Rangecc((iRangecc){ constBegin_String(url),
795 constBegin_String(url) + fragPos })); 796 constBegin_String(url) + fragPos }));
796 delete_String(head); 797 delete_String(head);
797 } 798 }
798 else { 799 else {
799 format_String(cmd, "open fromsidebar:1 newtab:%d url:%s", newTab, cstr_String(url)); 800 format_String(cmd,
801 "open fromsidebar:1 newtab:%d newwindow:%d url:%s",
802 newTab,
803 newWindow,
804 cstr_String(url));
800 } 805 }
801 return cmd; 806 return cmd;
802 } 807 }
diff --git a/src/gmutil.h b/src/gmutil.h
index 01eb8e52..e4284cfd 100644
--- a/src/gmutil.h
+++ b/src/gmutil.h
@@ -151,4 +151,4 @@ iRangecc mediaTypeWithoutParameters_Rangecc (iRangecc mime);
151const iString * findContainerArchive_Path (const iString *path); 151const iString * findContainerArchive_Path (const iString *path);
152 152
153 153
154const iString * feedEntryOpenCommand_String (const iString *url, int newTab); /* checks fragment */ 154const iString * feedEntryOpenCommand_String (const iString *url, int newTab, int newWindow); /* checks fragment */
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 76c26e27..99039ff5 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -5071,10 +5071,9 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
5071 iArray items; 5071 iArray items;
5072 init_Array(&items, sizeof(iMenuItem)); 5072 init_Array(&items, sizeof(iMenuItem));
5073 if (d->contextLink) { 5073 if (d->contextLink) {
5074 /* Context menu for a link. */ 5074 /* Construct the link context menu, depending on what kind of link was clicked. */
5075 interactingWithLink_DocumentWidget_(d, d->contextLink->linkId); /* perhaps will be triggered */ 5075 interactingWithLink_DocumentWidget_(d, d->contextLink->linkId); /* perhaps will be triggered */
5076 const iString *linkUrl = linkUrl_GmDocument(view->doc, d->contextLink->linkId); 5076 const iString *linkUrl = linkUrl_GmDocument(view->doc, d->contextLink->linkId);
5077// const int linkFlags = linkFlags_GmDocument(d->doc, d->contextLink->linkId);
5078 const iRangecc scheme = urlScheme_String(linkUrl); 5077 const iRangecc scheme = urlScheme_String(linkUrl);
5079 const iBool isGemini = equalCase_Rangecc(scheme, "gemini"); 5078 const iBool isGemini = equalCase_Rangecc(scheme, "gemini");
5080 iBool isNative = iFalse; 5079 iBool isNative = iFalse;
@@ -5086,39 +5085,48 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
5086 format_CStr("```%s", cstr_String(infoText)), 5085 format_CStr("```%s", cstr_String(infoText)),
5087 0, 0, NULL }); 5086 0, 0, NULL });
5088 } 5087 }
5089 if (willUseProxy_App(scheme) || isGemini || 5088 if (isGemini ||
5089 willUseProxy_App(scheme) ||
5090 equalCase_Rangecc(scheme, "data") ||
5090 equalCase_Rangecc(scheme, "file") || 5091 equalCase_Rangecc(scheme, "file") ||
5091 equalCase_Rangecc(scheme, "finger") || 5092 equalCase_Rangecc(scheme, "finger") ||
5092 equalCase_Rangecc(scheme, "gopher")) { 5093 equalCase_Rangecc(scheme, "gopher")) {
5093 isNative = iTrue; 5094 isNative = iTrue;
5094 /* Regular links that we can open. */ 5095 /* Regular links that we can open. */
5095 pushBackN_Array( 5096 pushBackN_Array(&items,
5096 &items, 5097 (iMenuItem[]){
5097 (iMenuItem[]){ { openTab_Icon " ${link.newtab}", 5098 { openTab_Icon " ${link.newtab}",
5098 0, 5099 0,
5099 0, 5100 0,
5100 format_CStr("!open newtab:1 origin:%s url:%s", 5101 format_CStr("!open newtab:1 origin:%s url:%s",
5101 cstr_String(id_Widget(w)), 5102 cstr_String(id_Widget(w)),
5102 cstr_String(linkUrl)) }, 5103 cstr_String(linkUrl)) },
5103 { openTabBg_Icon " ${link.newtab.background}", 5104 { openTabBg_Icon " ${link.newtab.background}",
5104 0, 5105 0,
5105 0, 5106 0,
5106 format_CStr("!open newtab:2 origin:%s url:%s", 5107 format_CStr("!open newtab:2 origin:%s url:%s",
5107 cstr_String(id_Widget(w)), 5108 cstr_String(id_Widget(w)),
5108 cstr_String(linkUrl)) }, 5109 cstr_String(linkUrl)) },
5109 { "${link.side}", 5110 { "${link.side}",
5110 0, 5111 0,
5111 0, 5112 0,
5112 format_CStr("!open newtab:4 origin:%s url:%s", 5113 format_CStr("!open newtab:4 origin:%s url:%s",
5113 cstr_String(id_Widget(w)), 5114 cstr_String(id_Widget(w)),
5114 cstr_String(linkUrl)) }, 5115 cstr_String(linkUrl)) },
5115 { "${link.side.newtab}", 5116 { "${link.side.newtab}",
5116 0, 5117 0,
5117 0, 5118 0,
5118 format_CStr("!open newtab:5 origin:%s url:%s", 5119 format_CStr("!open newtab:5 origin:%s url:%s",
5119 cstr_String(id_Widget(w)), 5120 cstr_String(id_Widget(w)),
5120 cstr_String(linkUrl)) } }, 5121 cstr_String(linkUrl)) },
5121 4); 5122 { openWindow_Icon " ${link.newwindow}",
5123 0,
5124 0,
5125 format_CStr("!open newwindow:1 origin:%s url:%s",
5126 cstr_String(id_Widget(w)),
5127 cstr_String(linkUrl)) },
5128 },
5129 5);
5122 if (deviceType_App() == phone_AppDeviceType) { 5130 if (deviceType_App() == phone_AppDeviceType) {
5123 removeN_Array(&items, size_Array(&items) - 2, iInvalidSize); 5131 removeN_Array(&items, size_Array(&items) - 2, iInvalidSize);
5124 } 5132 }
diff --git a/src/ui/lookupwidget.c b/src/ui/lookupwidget.c
index f14170ad..dc3264a2 100644
--- a/src/ui/lookupwidget.c
+++ b/src/ui/lookupwidget.c
@@ -568,7 +568,7 @@ static void presentResults_LookupWidget_(iLookupWidget *d) {
568 cstr_String(&res->label), 568 cstr_String(&res->label),
569 uiText_ColorEscape, 569 uiText_ColorEscape,
570 cstr_String(&res->meta)); 570 cstr_String(&res->meta));
571 const iString *cmd = feedEntryOpenCommand_String(&res->url, 0); 571 const iString *cmd = feedEntryOpenCommand_String(&res->url, 0, 0);
572 if (cmd) { 572 if (cmd) {
573 set_String(&item->command, cmd); 573 set_String(&item->command, cmd);
574 } 574 }
diff --git a/src/ui/root.c b/src/ui/root.c
index 7e4b4863..9dee50ae 100644
--- a/src/ui/root.c
+++ b/src/ui/root.c
@@ -56,7 +56,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
56#if defined (iPlatformPcDesktop) 56#if defined (iPlatformPcDesktop)
57/* TODO: Submenus wouldn't hurt here. */ 57/* TODO: Submenus wouldn't hurt here. */
58static const iMenuItem navMenuItems_[] = { 58static const iMenuItem navMenuItems_[] = {
59 { add_Icon " ${menu.newtab}", 't', KMOD_PRIMARY, "tabs.new" }, 59 { openWindow_Icon " ${menu.newwindow}", SDLK_n, KMOD_PRIMARY, "window.new" },
60 { add_Icon " ${menu.newtab}", SDLK_t, KMOD_PRIMARY, "tabs.new" },
60 { "${menu.openlocation}", SDLK_l, KMOD_PRIMARY, "navigate.focus" }, 61 { "${menu.openlocation}", SDLK_l, KMOD_PRIMARY, "navigate.focus" },
61 { "---" }, 62 { "---" },
62 { download_Icon " " saveToDownloads_Label, SDLK_s, KMOD_PRIMARY, "document.save" }, 63 { download_Icon " " saveToDownloads_Label, SDLK_s, KMOD_PRIMARY, "document.save" },
diff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c
index 73023a4f..0322b2a9 100644
--- a/src/ui/sidebarwidget.c
+++ b/src/ui/sidebarwidget.c
@@ -414,9 +414,13 @@ static void updateItemsWithFlags_SidebarWidget_(iSidebarWidget *d, iBool keepAct
414 } 414 }
415 d->menu = makeMenu_Widget( 415 d->menu = makeMenu_Widget(
416 as_Widget(d), 416 as_Widget(d),
417 (iMenuItem[]){ { openTab_Icon " ${feeds.entry.newtab}", 0, 0, "feed.entry.opentab" }, 417 (iMenuItem[]){ { openTab_Icon " ${menu.opentab}", 0, 0, "feed.entry.open newtab:1" },
418 { openTabBg_Icon " ${menu.opentab.background}", 0, 0, "feed.entry.open newtab:2" },
419 { openWindow_Icon " ${menu.openwindow}", 0, 0, "feed.entry.open newwindow:1" },
420 { "---", 0, 0, NULL },
418 { circle_Icon " ${feeds.entry.markread}", 0, 0, "feed.entry.toggleread" }, 421 { circle_Icon " ${feeds.entry.markread}", 0, 0, "feed.entry.toggleread" },
419 { bookmark_Icon " ${feeds.entry.bookmark}", 0, 0, "feed.entry.bookmark" }, 422 { bookmark_Icon " ${feeds.entry.bookmark}", 0, 0, "feed.entry.bookmark" },
423 { "${menu.copyurl}", 0, 0, "feed.entry.copyurl" },
420 { "---", 0, 0, NULL }, 424 { "---", 0, 0, NULL },
421 { page_Icon " ${feeds.entry.openfeed}", 0, 0, "feed.entry.openfeed" }, 425 { page_Icon " ${feeds.entry.openfeed}", 0, 0, "feed.entry.openfeed" },
422 { edit_Icon " ${feeds.edit}", 0, 0, "feed.entry.edit" }, 426 { edit_Icon " ${feeds.edit}", 0, 0, "feed.entry.edit" },
@@ -424,7 +428,7 @@ static void updateItemsWithFlags_SidebarWidget_(iSidebarWidget *d, iBool keepAct
424 { "---", 0, 0, NULL }, 428 { "---", 0, 0, NULL },
425 { check_Icon " ${feeds.markallread}", SDLK_a, KMOD_SHIFT, "feeds.markallread" }, 429 { check_Icon " ${feeds.markallread}", SDLK_a, KMOD_SHIFT, "feeds.markallread" },
426 { reload_Icon " ${feeds.refresh}", SDLK_r, KMOD_PRIMARY | KMOD_SHIFT, "feeds.refresh" } }, 430 { reload_Icon " ${feeds.refresh}", SDLK_r, KMOD_PRIMARY | KMOD_SHIFT, "feeds.refresh" } },
427 10); 431 13);
428 d->modeMenu = makeMenu_Widget( 432 d->modeMenu = makeMenu_Widget(
429 as_Widget(d), 433 as_Widget(d),
430 (iMenuItem[]){ 434 (iMenuItem[]){
@@ -491,6 +495,7 @@ static void updateItemsWithFlags_SidebarWidget_(iSidebarWidget *d, iBool keepAct
491 as_Widget(d), 495 as_Widget(d),
492 (iMenuItem[]){ { openTab_Icon " ${menu.opentab}", 0, 0, "bookmark.open newtab:1" }, 496 (iMenuItem[]){ { openTab_Icon " ${menu.opentab}", 0, 0, "bookmark.open newtab:1" },
493 { openTabBg_Icon " ${menu.opentab.background}", 0, 0, "bookmark.open newtab:2" }, 497 { openTabBg_Icon " ${menu.opentab.background}", 0, 0, "bookmark.open newtab:2" },
498 { openWindow_Icon " ${menu.openwindow}", 0, 0, "bookmark.open newwindow:1" },
494 { "---", 0, 0, NULL }, 499 { "---", 0, 0, NULL },
495 { edit_Icon " ${menu.edit}", 0, 0, "bookmark.edit" }, 500 { edit_Icon " ${menu.edit}", 0, 0, "bookmark.edit" },
496 { copy_Icon " ${menu.dup}", 0, 0, "bookmark.dup" }, 501 { copy_Icon " ${menu.dup}", 0, 0, "bookmark.dup" },
@@ -502,11 +507,11 @@ static void updateItemsWithFlags_SidebarWidget_(iSidebarWidget *d, iBool keepAct
502 { "---", 0, 0, NULL }, 507 { "---", 0, 0, NULL },
503 { delete_Icon " " uiTextCaution_ColorEscape "${bookmark.delete}", 0, 0, "bookmark.delete" }, 508 { delete_Icon " " uiTextCaution_ColorEscape "${bookmark.delete}", 0, 0, "bookmark.delete" },
504 { "---", 0, 0, NULL }, 509 { "---", 0, 0, NULL },
505 { add_Icon " ${menu.newfolder}", 0, 0, "bookmark.addfolder" }, 510 { folder_Icon " ${menu.newfolder}", 0, 0, "bookmark.addfolder" },
506 { upDownArrow_Icon " ${menu.sort.alpha}", 0, 0, "bookmark.sortfolder" }, 511 { upDownArrow_Icon " ${menu.sort.alpha}", 0, 0, "bookmark.sortfolder" },
507 { "---", 0, 0, NULL }, 512 { "---", 0, 0, NULL },
508 { reload_Icon " ${bookmarks.reload}", 0, 0, "bookmarks.reload.remote" } }, 513 { reload_Icon " ${bookmarks.reload}", 0, 0, "bookmarks.reload.remote" } },
509 17); 514 18);
510 d->modeMenu = makeMenu_Widget( 515 d->modeMenu = makeMenu_Widget(
511 as_Widget(d), 516 as_Widget(d),
512 (iMenuItem[]){ { bookmark_Icon " ${menu.page.bookmark}", SDLK_d, KMOD_PRIMARY, "bookmark.add" }, 517 (iMenuItem[]){ { bookmark_Icon " ${menu.page.bookmark}", SDLK_d, KMOD_PRIMARY, "bookmark.add" },
@@ -571,13 +576,17 @@ static void updateItemsWithFlags_SidebarWidget_(iSidebarWidget *d, iBool keepAct
571 d->menu = makeMenu_Widget( 576 d->menu = makeMenu_Widget(
572 as_Widget(d), 577 as_Widget(d),
573 (iMenuItem[]){ 578 (iMenuItem[]){
579 { openTab_Icon " ${menu.opentab}", 0, 0, "history.open newtab:1" },
580 { openTabBg_Icon " ${menu.opentab.background}", 0, 0, "history.open newtab:2" },
581 { openWindow_Icon " ${menu.openwindow}", 0, 0, "history.open newwindow:1" },
582 { "---" },
574 { "${menu.copyurl}", 0, 0, "history.copy" }, 583 { "${menu.copyurl}", 0, 0, "history.copy" },
575 { bookmark_Icon " ${sidebar.entry.bookmark}", 0, 0, "history.addbookmark" }, 584 { bookmark_Icon " ${sidebar.entry.bookmark}", 0, 0, "history.addbookmark" },
576 { "---", 0, 0, NULL }, 585 { "---", 0, 0, NULL },
577 { close_Icon " ${menu.forgeturl}", 0, 0, "history.delete" }, 586 { close_Icon " ${menu.forgeturl}", 0, 0, "history.delete" },
578 { "---", 0, 0, NULL }, 587 { "---", 0, 0, NULL },
579 { delete_Icon " " uiTextCaution_ColorEscape "${history.clear}", 0, 0, "history.clear confirm:1" }, 588 { delete_Icon " " uiTextCaution_ColorEscape "${history.clear}", 0, 0, "history.clear confirm:1" },
580 }, 6); 589 }, 10);
581 d->modeMenu = makeMenu_Widget( 590 d->modeMenu = makeMenu_Widget(
582 as_Widget(d), 591 as_Widget(d),
583 (iMenuItem[]){ 592 (iMenuItem[]){
@@ -981,7 +990,7 @@ static void itemClicked_SidebarWidget_(iSidebarWidget *d, iSidebarItem *item, si
981 } 990 }
982 case feeds_SidebarMode: { 991 case feeds_SidebarMode: {
983 postCommandString_Root(get_Root(), 992 postCommandString_Root(get_Root(),
984 feedEntryOpenCommand_String(&item->url, openTabMode_Sym(modState_Keys()))); 993 feedEntryOpenCommand_String(&item->url, openTabMode_Sym(modState_Keys()), 0));
985 break; 994 break;
986 } 995 }
987 case bookmarks_SidebarMode: 996 case bookmarks_SidebarMode:
@@ -1641,8 +1650,11 @@ static iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)
1641 else if (startsWith_CStr(cmd, "feed.entry.") && d->mode == feeds_SidebarMode) { 1650 else if (startsWith_CStr(cmd, "feed.entry.") && d->mode == feeds_SidebarMode) {
1642 const iSidebarItem *item = d->contextItem; 1651 const iSidebarItem *item = d->contextItem;
1643 if (item) { 1652 if (item) {
1644 if (isCommand_Widget(w, ev, "feed.entry.opentab")) { 1653 if (isCommand_Widget(w, ev, "feed.entry.open")) {
1645 postCommandString_Root(get_Root(), feedEntryOpenCommand_String(&item->url, 1)); 1654 const char *cmd = command_UserEvent(ev);
1655 postCommandString_Root(get_Root(), feedEntryOpenCommand_String(&item->url,
1656 argLabel_Command(cmd, "newtab"),
1657 argLabel_Command(cmd, "newwindow")));
1646 return iTrue; 1658 return iTrue;
1647 } 1659 }
1648 if (isCommand_Widget(w, ev, "feed.entry.toggleread")) { 1660 if (isCommand_Widget(w, ev, "feed.entry.toggleread")) {
diff --git a/src/ui/window.c b/src/ui/window.c
index 6f680cd4..b0de0557 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -1567,6 +1567,23 @@ void setKeyboardHeight_MainWindow(iMainWindow *d, int height) {
1567 } 1567 }
1568} 1568}
1569 1569
1570iObjectList *listDocuments_MainWindow(iMainWindow *d, const iRoot *rootOrNull) {
1571 iObjectList *docs = new_ObjectList();
1572 iForIndices(i, d->base.roots) {
1573 iRoot *root = d->base.roots[i];
1574 if (!root) continue;
1575 if (!rootOrNull || root == rootOrNull) {
1576 const iWidget *tabs = findChild_Widget(root->widget, "doctabs");
1577 iForEach(ObjectList, i, children_Widget(findChild_Widget(tabs, "tabs.pages"))) {
1578 if (isInstance_Object(i.object, &Class_DocumentWidget)) {
1579 pushBack_ObjectList(docs, i.object);
1580 }
1581 }
1582 }
1583 }
1584 return docs;
1585}
1586
1570void checkPendingSplit_MainWindow(iMainWindow *d) { 1587void checkPendingSplit_MainWindow(iMainWindow *d) {
1571 if (d->splitMode != d->pendingSplitMode) { 1588 if (d->splitMode != d->pendingSplitMode) {
1572 setSplitMode_MainWindow(d, d->pendingSplitMode); 1589 setSplitMode_MainWindow(d, d->pendingSplitMode);
diff --git a/src/ui/window.h b/src/ui/window.h
index c7d59380..c3c34e1b 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -187,6 +187,7 @@ void setTitle_MainWindow (iMainWindow *, const iString *title
187void setSnap_MainWindow (iMainWindow *, int snapMode); 187void setSnap_MainWindow (iMainWindow *, int snapMode);
188void setFreezeDraw_MainWindow (iMainWindow *, iBool freezeDraw); 188void setFreezeDraw_MainWindow (iMainWindow *, iBool freezeDraw);
189void setKeyboardHeight_MainWindow (iMainWindow *, int height); 189void setKeyboardHeight_MainWindow (iMainWindow *, int height);
190iObjectList *listDocuments_MainWindow (iMainWindow *, const iRoot *rootOrNull);
190void setSplitMode_MainWindow (iMainWindow *, int splitMode); 191void setSplitMode_MainWindow (iMainWindow *, int splitMode);
191void checkPendingSplit_MainWindow (iMainWindow *); 192void checkPendingSplit_MainWindow (iMainWindow *);
192void swapRoots_MainWindow (iMainWindow *); 193void swapRoots_MainWindow (iMainWindow *);