Lagrange [work/v1.17]

Navigating to parent directory or site root

=> c9b1a0d3e42d27ec2786103ec3bc812a5d38da6c

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
     }
 }
 
Proxy Information
Original URL
gemini://git.skyjake.fi/lagrange/work%2Fv1.17/cdiff/c9b1a0d3e42d27ec2786103ec3bc812a5d38da6c
Status Code
Success (20)
Meta
text/gemini; charset=utf-8
Capsule Response Time
67.137717 milliseconds
Gemini-to-HTML Time
0.509434 milliseconds

This content has been proxied by September (ba2dc).