diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index c71758be..3fc7e841 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c @@ -225,6 +225,8 @@ void init_DocumentWidget(iDocumentWidget *d) { #endif addAction_Widget(w, navigateBack_KeyShortcut, "navigate.back"); addAction_Widget(w, navigateForward_KeyShortcut, "navigate.forward"); + addAction_Widget(w, navigateParent_KeyShortcut, "navigate.parent"); + addAction_Widget(w, navigateRoot_KeyShortcut, "navigate.root"); }  void deinit_DocumentWidget(iDocumentWidget *d) { @@ -259,13 +261,6 @@ static void requestUpdated_DocumentWidget_(iAnyObject *obj) { } }  -#if 0 -static void requestTimedOut_DocumentWidget_(iAnyObject *obj) { - iDocumentWidget *d = obj; - postCommandf_App("document.request.timeout doc:%p request:%p", d, d->request); -} -#endif - static void requestFinished_DocumentWidget_(iAnyObject *obj) { iDocumentWidget *d = obj; postCommand_Widget(obj, "document.request.finished doc:%p request:%p", d, d->request); @@ -301,6 +296,16 @@ static iRect documentBounds_DocumentWidget_(const iDocumentWidget *d) { return rect; }  +static iRect siteBannerRect_DocumentWidget_(const iDocumentWidget *d) { + const iGmRun *banner = siteBanner_GmDocument(d->doc); + if (!banner) { + return zero_Rect(); + } + const iRect docBounds = documentBounds_DocumentWidget_(d); + const iInt2 origin = addY_I2(topLeft_Rect(docBounds), -value_Anim(&d->scrollY)); + return moved_Rect(banner->visBounds, origin); +} + static int forceBreakWidth_DocumentWidget_(const iDocumentWidget *d) { if (equalCase_Rangecc(urlScheme_String(d->mod.url), "gopher")) { return documentWidth_DocumentWidget_(d); @@ -1397,13 +1402,6 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) postCommandf_App("document.changed url:%s", cstr_String(d->mod.url)); return iFalse; } -#if 0 - else if (equal_Command(cmd, "document.request.timeout") && - pointerLabel_Command(cmd, "request") == d->request) { - cancel_GmRequest(d->request); - return iFalse; - } -#endif else if (equal_Command(cmd, "media.updated") || equal_Command(cmd, "media.finished")) { return handleMediaCommand_DocumentWidget_(d, cmd); } @@ -1528,6 +1526,32 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) goForward_History(d->mod.history); return iTrue; } + else if (equal_Command(cmd, "navigate.parent") && document_App() == d) { + iUrl parts; + init_Url(&parts, d->mod.url); + /* Remove the last path segment. */ + if (size_Range(&parts.path) > 1) { + if (parts.path.end[-1] == '/') { + parts.path.end--; + } + while (parts.path.end > parts.path.start) { + if (parts.path.end[-1] == '/') break; + parts.path.end--; + } + postCommandf_App( + "open url:%s", + cstr_Rangecc((iRangecc){ constBegin_String(d->mod.url), parts.path.end })); + } + return iTrue; + } + else if (equal_Command(cmd, "navigate.root") && document_App() == d) { + iUrl parts; + init_Url(&parts, d->mod.url); + postCommandf_App( + "open url:%s/", + cstr_Rangecc((iRangecc){ constBegin_String(d->mod.url), parts.path.start })); + return iTrue; + } else if (equalWidget_Command(cmd, w, "scroll.moved")) { init_Anim(&d->scrollY, arg_Command(cmd)); updateVisible_DocumentWidget_(d); @@ -1922,11 +1946,15 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e } else if (ev->type == SDL_MOUSEMOTION) { iChangeFlags(d->flags, noHoverWhileScrolling_DocumentWidgetFlag, iFalse); + const iInt2 mpos = init_I2(ev->motion.x, ev->motion.y); if (isVisible_Widget(d->menu)) { setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_ARROW); } + else if (contains_Rect(siteBannerRect_DocumentWidget_(d), mpos)) { + setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_HAND); + } else { - updateHover_DocumentWidget_(d, init_I2(ev->motion.x, ev->motion.y)); + updateHover_DocumentWidget_(d, mpos); } updateOutlineOpacity_DocumentWidget_(d); } @@ -2006,11 +2034,13 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e (iMenuItem[]){ { "Go Back", navigateBack_KeyShortcut, "navigate.back" }, { "Go Forward", navigateForward_KeyShortcut, "navigate.forward" }, + { "Go to Parent", navigateParent_KeyShortcut, "navigate.parent" }, + { "Go to Root", navigateRoot_KeyShortcut, "navigate.root" }, + { "---", 0, 0, NULL }, { "Reload Page", reload_KeyShortcut, "navigate.reload" }, { "---", 0, 0, NULL }, - { "Copy Page URL", 0, 0, "document.copylink" }, - { "---", 0, 0, NULL } }, - 6); + { "Copy Page URL", 0, 0, "document.copylink" } }, + 8); if (isEmpty_Range(&d->selectMark)) { pushBackN_Array( &items, @@ -2144,6 +2174,10 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e d->selectMark = iNullRange; refresh_Widget(w); } + /* Clicking on the top/side banner navigates to site root. */ + if (contains_Rect(siteBannerRect_DocumentWidget_(d), pos_Click(&d->click))) { + postCommand_Widget(d, "navigate.root"); + } } return iTrue; case double_ClickResult: diff --git a/src/ui/keys.h b/src/ui/keys.h index a4c8f348..5bc9141c 100644 --- a/src/ui/keys.h +++ b/src/ui/keys.h @@ -32,6 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ # define nextTab_KeyShortcut SDLK_RIGHTBRACKET, KMOD_SHIFT | KMOD_PRIMARY # define navigateBack_KeyShortcut SDLK_LEFT, KMOD_PRIMARY # define navigateForward_KeyShortcut SDLK_RIGHT, KMOD_PRIMARY +# define navigateParent_KeyShortcut SDLK_UP, KMOD_PRIMARY +# define navigateRoot_KeyShortcut SDLK_UP, KMOD_SHIFT | KMOD_PRIMARY # define byWord_KeyModifier KMOD_ALT # define byLine_KeyModifier KMOD_PRIMARY #else @@ -40,6 +42,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ # define nextTab_KeyShortcut SDLK_PAGEDOWN, KMOD_PRIMARY # define navigateBack_KeyShortcut SDLK_LEFT, KMOD_ALT # define navigateForward_KeyShortcut SDLK_RIGHT, KMOD_ALT +# define navigateParent_KeyShortcut SDLK_UP, KMOD_ALT +# define navigateRoot_KeyShortcut SDLK_UP, KMOD_SHIFT | KMOD_ALT # define byWord_KeyModifier KMOD_CTRL # define byLine_KeyModifier 0 #endif diff --git a/src/ui/util.c b/src/ui/util.c index ae3ddb18..bf044c03 100644 --- a/src/ui/util.c +++ b/src/ui/util.c @@ -92,6 +92,12 @@ void toString_Sym(int key, int kmods, iString *str) { else if (key == SDLK_RIGHT) { appendChar_String(str, 0x2192); } + else if (key == SDLK_UP) { + appendChar_String(str, 0x2191); + } + else if (key == SDLK_DOWN) { + appendChar_String(str, 0x2193); + } else if (key < 128 && (isalnum(key) || ispunct(key))) { appendChar_String(str, upper_Char(key)); } diff --git a/src/ui/window.c b/src/ui/window.c index 115dd04b..a69dd7db 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -146,6 +146,8 @@ static const iMenuItem viewMenuItems[] = { { "---", 0, 0, NULL }, { "Go Back", SDLK_LEFTBRACKET, KMOD_PRIMARY, "navigate.back" }, { "Go Forward", SDLK_RIGHTBRACKET, KMOD_PRIMARY, "navigate.forward" }, + { "Go to Parent", navigateParent_KeyShortcut, "navigate.parent" }, + { "Go to Root", navigateRoot_KeyShortcut, "navigate.root" }, { "Reload Page", reload_KeyShortcut, "navigate.reload" }, { "---", 0, 0, NULL }, { "Zoom In", SDLK_EQUALS, KMOD_PRIMARY, "zoom.delta arg:10" }, @@ -473,14 +475,12 @@ static void setupUserInterface_Window(iWindow *d) { /* Global keyboard shortcuts. */ { addAction_Widget(d->root, prevTab_KeyShortcut, "tabs.prev"); addAction_Widget(d->root, nextTab_KeyShortcut, "tabs.next"); -#if !defined (iHaveNativeMenus) addAction_Widget(d->root, 'l', KMOD_PRIMARY, "navigate.focus"); addAction_Widget(d->root, 'f', KMOD_PRIMARY, "focus.set id:find.input"); addAction_Widget(d->root, '1', KMOD_PRIMARY, "sidebar.mode arg:0 toggle:1"); addAction_Widget(d->root, '2', KMOD_PRIMARY, "sidebar.mode arg:1 toggle:1"); addAction_Widget(d->root, '3', KMOD_PRIMARY, "sidebar.mode arg:2 toggle:1"); addAction_Widget(d->root, '4', KMOD_PRIMARY, "sidebar.mode arg:3 toggle:1"); -#endif } }