summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2022-02-20 09:33:20 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2022-02-20 09:33:20 +0200
commited14d3467d6046ddfa66c3143a340428aeef66ae (patch)
tree1c06f4f34c5caf874847d2d6cfba206f89cd4f33 /src
parent44214359c0f95dcce3a1390506e9fd74202d5ae7 (diff)
Adding context items to open in new window
Diffstat (limited to 'src')
-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
11 files changed, 119 insertions, 64 deletions
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 *);