From a6314e152b2d2f306bcbb880356d3890efbfc89e Mon Sep 17 00:00:00 2001

From: =?UTF-8?q?Jaakko=20Ker=C3=A4nen?= jaakko.keranen@iki.fi

Date: Sat, 21 Nov 2020 15:07:49 +0200

Subject: [PATCH 1/1] Keyboard navigation mode for home row keys

Now there are keybindings for activating the keyboard navigation modes. The modifier-based mode remains as it was before, focusing on numbers, while the home row mode uses a separate activation key.

One can erase the bindings to disable the corresponding modes.

IssueID #34


res/about/version.gmi | 5 +-

src/ui/bindingswidget.c | 6 ++

src/ui/documentwidget.c | 158 +++++++++++++++++++++++-----------------

src/ui/keys.c | 38 +++++-----

src/ui/util.c | 8 ++

src/ui/util.h | 1 +

6 files changed, 128 insertions(+), 88 deletions(-)

diff --git a/res/about/version.gmi b/res/about/version.gmi

index 1b8e502a..48b4cbd1 100644

--- a/res/about/version.gmi

+++ b/res/about/version.gmi

@@ -7,9 +7,10 @@

Release notes

0.10

-* Added option to load inline images when pressing Space or ↓ for a more focused reading experience — just keep tapping on a single key to proceed. If an image link is visible, it will be loaded instead of scrolling. This option is disabled by default.

+* Added option to load inline images when pressing Space or ↓ for a more focused reading experience — just keep tapping a single key to proceed. If an image link is visible, it will be loaded instead of scrolling. This option is disabled by default.

-* Added a keybinding to activate keyboard link navigation mode (default is "F").

+* Added a new keyboard link navigation mode focusing on the home row keys. The default keybinding for this is "F".

+* Added a keybinding to activate keyboard link modifier mode. The keyboard link keys are active while the modifier is held down. The default is ${ALT}.

diff --git a/src/ui/bindingswidget.c b/src/ui/bindingswidget.c

index ff68ea7b..dee844db 100644

--- a/src/ui/bindingswidget.c

+++ b/src/ui/bindingswidget.c

@@ -195,6 +195,12 @@ static iBool processEvent_BindingsWidget_(iBindingsWidget *d, const SDL_Event *e

         postCommand_App("bindings.changed");

         return iTrue;

     }

 }

 return processEvent_Widget(w, ev);

}

diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c

index b1c166aa..3cf564ac 100644

--- a/src/ui/documentwidget.c

+++ b/src/ui/documentwidget.c

@@ -125,11 +125,17 @@ enum iDocumentWidgetFlag {

 showLinkNumbers_DocumentWidgetFlag       = iBit(3),

};

+enum iDocumentLinkOrdinalMode {

+};

struct Impl_DocumentWidget {

 iWidget        widget;

 enum iRequestState state;

 iPersistentDocumentState mod;

 int            flags;

 iString *      titleUser;

 iGmRequest *   request;

 iAtomicInt     isRequestUpdated; /* request has new content, need to parse it */

@@ -228,7 +234,6 @@ void init_DocumentWidget(iDocumentWidget *d) {

 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) {

@@ -371,6 +376,15 @@ static void invalidateLink_DocumentWidget_(iDocumentWidget *d, iGmLinkId id) {

 }

}

+static void invalidateVisibleLinks_DocumentWidget_(iDocumentWidget *d) {

+}

static void updateHover_DocumentWidget_(iDocumentWidget *d, iInt2 mouse) {

 const iWidget *w            = constAs_Widget(d);

 const iRect    docBounds    = documentBounds_DocumentWidget_(d);

@@ -969,7 +983,7 @@ static void smoothScroll_DocumentWidget_(iDocumentWidget *d, int offset, int dur

 /* Get rid of link numbers when scrolling. */

 if (offset && d->flags & showLinkNumbers_DocumentWidgetFlag) {

     d->flags &= ~showLinkNumbers_DocumentWidgetFlag;

 }

 if (!prefs_App()->smoothScrolling) {

     duration = 0; /* always instant */

@@ -1542,8 +1556,14 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)

     return iTrue;

 }

 else if (equal_Command(cmd, "document.linkkeys") && document_App() == d) {

     refresh_Widget(d);

     return iTrue;

 }

@@ -1815,45 +1835,75 @@ static iBool processPlayerEvents_DocumentWidget_(iDocumentWidget *d, const SDL_E

 return iFalse;

}

-static size_t linkOrdinalFromKey_(int key) {

+/* Sorted by proximity to F and J. */

+static const int homeRowKeys_[] = {

+};

+static size_t linkOrdinalFromKey_DocumentWidget_(const iDocumentWidget *d, int key) {

#if defined (iPlatformApple)

#endif

 return ord;

}

-static iChar linkOrdinalChar_(size_t ord) {

+static iChar linkOrdinalChar_DocumentWidget_(const iDocumentWidget *d, size_t ord) {

#if defined (iPlatformApple)

#else

#endif

 return 0;

}

@@ -1866,31 +1916,11 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e

     }

     return iTrue;

 }

-// d->smoothContinue = iFalse;

 if (ev->type == SDL_KEYDOWN) {

     const int key = ev->key.keysym.sym;

     if ((d->flags & showLinkNumbers_DocumentWidgetFlag) &&

         ((key >= '1' && key <= '9') || (key >= 'a' && key <= 'z'))) {

         iConstForEach(PtrArray, i, &d->visibleLinks) {

             if (ord == iInvalidPos) break;

             const iGmRun *run = i.ptr;

@@ -1904,6 +1934,8 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e

                                  cstr_String(absoluteUrl_String(

                                  d->mod.url, linkUrl_GmDocument(d->doc, run->linkId))));

                 iChangeFlags(d->flags, showLinkNumbers_DocumentWidgetFlag, iFalse);

                 return iTrue;

             }

         }

@@ -1912,19 +1944,11 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e

         case SDLK_ESCAPE:

             if (d->flags & showLinkNumbers_DocumentWidgetFlag && document_App() == d) {

                 iChangeFlags(d->flags, showLinkNumbers_DocumentWidgetFlag, iFalse);

                 refresh_Widget(d);

                 return iTrue;

             }

             break;

#if 1

         case SDLK_KP_1:

         case '`': {

@@ -2374,11 +2398,11 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {

 else {

     if (d->showLinkNumbers && run->linkId && run->flags & decoration_GmRunFlag) {

         const size_t ord = visibleLinkOrdinal_DocumentWidget_(d->widget, run->linkId);

         if (ordChar) {

             drawString_Text(run->font,

                             init_I2(d->viewPos.x - gap_UI / 3, visPos.y),

                             collect_String(newUnicodeN_String(&ordChar, 1)));

             goto runDrawn;

         }

diff --git a/src/ui/keys.c b/src/ui/keys.c

index ea874343..d42ecfba 100644

--- a/src/ui/keys.c

+++ b/src/ui/keys.c

@@ -57,7 +57,8 @@ static void clear_Keys_(iKeys *d) {

}

enum iBindFlag {

};

/* TODO: This indirection could be used for localization, although all UI strings

@@ -73,7 +74,8 @@ static const struct { int id; iMenuItem bind; int flags; } defaultBindings_[] =

 { 31, { "Go forward",                navigateForward_KeyShortcut,   "navigate.forward"   }, 0 },

 { 32, { "Go to parent directory",    navigateParent_KeyShortcut,    "navigate.parent"    }, 0 },

 { 33, { "Go to site root",           navigateRoot_KeyShortcut,      "navigate.root"      }, 0 },

 /* The following cannot currently be changed (built-in duplicates). */

 { 1000, { NULL, SDLK_SPACE, KMOD_SHIFT, "scroll.page arg:-1" }, argRepeat_BindFlag },

 { 1001, { NULL, SDLK_SPACE, 0, "scroll.page arg:1" }, argRepeat_BindFlag },

@@ -110,6 +112,11 @@ static void bindDefaults_(void) {

static iBinding *find_Keys_(iKeys *d, int key, int mods) {

 size_t pos;

 const iBinding elem = { .key = key, .mods = mods };

 if (locate_PtrSet(&d->lookup, &elem, &pos)) {

     return at_PtrSet(&d->lookup, pos);

@@ -138,8 +145,8 @@ static void updateLookup_Keys_(iKeys *d) {

void setKey_Binding(int id, int key, int mods) {

 iBinding *bind = findId_Keys_(&keys_, id);

 if (bind) {

     updateLookup_Keys_(&keys_);

 }

}

@@ -252,25 +259,18 @@ void setLabel_Keys(int id, const char *label) {

 }

}

-#if 0

-const iString *label_Keys(const char *command) {

-}

-#endif

iBool processEvent_Keys(const SDL_Event *ev) {

 iKeys *d = &keys_;

     const iBinding *bind = find_Keys_(d, ev->key.keysym.sym, keyMods_Sym(ev->key.keysym.mod));

     if (bind) {

         if (ev->key.repeat && (bind->flags & argRepeat_BindFlag)) {

             postCommandf_App("%s repeat:1", cstr_String(&bind->command));

         }

diff --git a/src/ui/util.c b/src/ui/util.c

index 559c5381..c1312062 100644

--- a/src/ui/util.c

+++ b/src/ui/util.c

@@ -117,6 +117,14 @@ iBool isMod_Sym(int key) {

        key == SDLK_LGUI || key == SDLK_RGUI || key == SDLK_LSHIFT || key == SDLK_RSHIFT;

}

+int normalizedMod_Sym(int key) {

+}

int keyMods_Sym(int kmods) {

 kmods &= (KMOD_SHIFT | KMOD_ALT | KMOD_CTRL | KMOD_GUI);

 /* Don't treat left/right modifiers differently. */

diff --git a/src/ui/util.h b/src/ui/util.h

index c0e3a04c..f7a67f9a 100644

--- a/src/ui/util.h

+++ b/src/ui/util.h

@@ -49,6 +49,7 @@ iLocalDef iBool isResize_UserEvent(const SDL_Event *d) {

#endif

iBool isMod_Sym (int key);

+int normalizedMod_Sym (int key);

int keyMods_Sym (int kmods); /* shift, alt, control, or gui */

void toString_Sym (int key, int kmods, iString *str);

--

2.25.1

Proxy Information
Original URL
gemini://git.skyjake.fi/lagrange/work%2Fv1.7/patch/a6314e152b2d2f306bcbb880356d3890efbfc89e.patch
Status Code
Success (20)
Meta
text/plain
Capsule Response Time
63.737975 milliseconds
Gemini-to-HTML Time
3.930382 milliseconds

This content has been proxied by September (ba2dc).