Lagrange [work/v1.8]

Handling keys while navigating via home row

=> 32cbf877ac137b28eb41a9084717707907c02d94

diff --git a/src/macos.h b/src/macos.h
index 22a6dfff..10cbba81 100644
--- a/src/macos.h
+++ b/src/macos.h
@@ -39,8 +39,10 @@ void    hideTitleBar_MacOS          (iWindow *window);
 void    insertMenuItems_MacOS       (const char *menuLabel, int atIndex, const iMenuItem *items, size_t count);
 void    removeMenu_MacOS            (int atIndex);
 void    enableMenu_MacOS            (const char *menuLabel, iBool enable);
+void    enableMenuIndex_MacOS       (int index, iBool enable);
 void    enableMenuItem_MacOS        (const char *menuItemCommand, iBool enable);
 void    enableMenuItemsByKey_MacOS  (int key, int kmods, iBool enable);
+void    enableMenuItemsOnHomeRow_MacOS(iBool enable);
 void    handleCommand_MacOS         (const char *cmd);
 
 void    showPopupMenu_MacOS         (iWidget *source, iInt2 windowCoord, const iMenuItem *items, size_t n);
diff --git a/src/macos.m b/src/macos.m
index cfbca488..28e349ea 100644
--- a/src/macos.m
+++ b/src/macos.m
@@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
 
 #include 
 #include 
+#include 
 
 #import 
 
@@ -439,6 +440,13 @@ void enableMenu_MacOS(const char *menuLabel, iBool enable) {
     [menuItem setEnabled:enable];
 }
 
+void enableMenuIndex_MacOS(int index, iBool enable) {
+    NSApplication *app = [NSApplication sharedApplication];
+    NSMenu *appMenu = [app mainMenu];
+    NSMenuItem *menuItem = [appMenu itemAtIndex:index];
+    [menuItem setEnabled:enable];        
+}
+
 void enableMenuItem_MacOS(const char *menuItemCommand, iBool enable) {
     NSApplication *app = [NSApplication sharedApplication];
     NSMenu *appMenu = [app mainMenu];
@@ -513,6 +521,47 @@ void enableMenuItemsByKey_MacOS(int key, int kmods, iBool enable) {
     delete_String(keyEquiv);
 }
 
+void enableMenuItemsOnHomeRow_MacOS(iBool enable) {
+    iStringSet *homeRowKeys = new_StringSet();
+    const char *keys[] = { /* Note: another array in documentwidget.c */
+        "f", "d", "s", "a",
+        "j", "k", "l",
+        "r", "e", "w", "q",
+        "u", "i", "o", "p",
+        "v", "c", "x", "z",
+        "m", "n",
+        "g", "h",
+        "b",
+        "t", "y"
+    };
+    iForIndices(i, keys) {
+        iString str;
+        initCStr_String(&str, keys[i]);
+        insert_StringSet(homeRowKeys, &str);
+        deinit_String(&str);
+    }
+    NSApplication *app = [NSApplication sharedApplication];
+    NSMenu *appMenu = [app mainMenu];
+    for (NSMenuItem *mainMenuItem in appMenu.itemArray) {
+        NSMenu *menu = mainMenuItem.submenu;
+        if (menu) {
+            for (NSMenuItem *menuItem in menu.itemArray) {
+                if (menuItem.keyEquivalentModifierMask == 0) {
+                    iString equiv;
+                    initCStr_String(&equiv, [menuItem.keyEquivalent
+                                                cStringUsingEncoding:NSUTF8StringEncoding]);
+                    if (contains_StringSet(homeRowKeys, &equiv)) {
+                        [menuItem setEnabled:enable];
+                        [menu setAutoenablesItems:NO];
+                    }
+                    deinit_String(&equiv);
+                }
+            }
+        }
+    }
+    iRelease(homeRowKeys);
+}
+
 static void setShortcut_NSMenuItem_(NSMenuItem *item, int key, int kmods) {
     NSEventModifierFlags modMask;
     iString *str = composeKeyEquivalent_(key, kmods, &modMask);
diff --git a/src/ui/bindingswidget.c b/src/ui/bindingswidget.c
index 4cf8df8e..13f9434e 100644
--- a/src/ui/bindingswidget.c
+++ b/src/ui/bindingswidget.c
@@ -143,12 +143,16 @@ static void setActiveItem_BindingsWidget_(iBindingsWidget *d, size_t pos) {
         item->isWaitingForEvent = iTrue;
         invalidateItem_ListWidget(d->list, d->activePos);
     }
-#if defined (iPlatformAppleDesktop)
+#if defined (iPlatformAppleDesktop) && defined (iHaveNativeContextMenus)
     /* Native menus must be disabled while grabbing keys so the shortcuts don't trigger. */
     const iBool enableNativeMenus = (d->activePos == iInvalidPos);
+    enableMenu_MacOS("${menu.title.file}", enableNativeMenus);
     enableMenu_MacOS("${menu.title.edit}", enableNativeMenus);
     enableMenu_MacOS("${menu.title.view}", enableNativeMenus);
+    enableMenu_MacOS("${menu.title.bookmarks}", enableNativeMenus);
     enableMenu_MacOS("${menu.title.identity}", enableNativeMenus);
+    enableMenuIndex_MacOS(6, enableNativeMenus);
+    enableMenuIndex_MacOS(7, enableNativeMenus);
 #endif
 }
 
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 46af5fcd..f83539f7 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -55,6 +55,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
 #include "visbuf.h"
 #include "visited.h"
 
+#if defined (iPlatformAppleDesktop)
+#   include "macos.h"
+#endif
 #if defined (iPlatformAppleMobile)
 #   include "ios.h"
 #endif
@@ -469,11 +472,18 @@ static void enableActions_DocumentWidget_(iDocumentWidget *d, iBool enable) {
 }
 
 static void setLinkNumberMode_DocumentWidget_(iDocumentWidget *d, iBool set) {
-    iChangeFlags(d->flags, showLinkNumbers_DocumentWidgetFlag, set);
-    /* Children have priority when handling events. */
-    enableActions_DocumentWidget_(d, !set);
-    if (d->menu) {
-        setFlags_Widget(d->menu, disabled_WidgetFlag, set);
+    if (((d->flags & showLinkNumbers_DocumentWidgetFlag) != 0) != set) {
+        iChangeFlags(d->flags, showLinkNumbers_DocumentWidgetFlag, set);
+        /* Children have priority when handling events. */
+        enableActions_DocumentWidget_(d, !set);
+#if defined (iPlatformAppleDesktop)
+        enableMenuItemsOnHomeRow_MacOS(!set);
+#endif
+        /* Ensure all keyboard events come here first. */
+        setKeyboardGrab_Widget(set ? as_Widget(d) : NULL);
+        if (d->menu) {
+            setFlags_Widget(d->menu, disabled_WidgetFlag, set);
+        }
     }
 }
 
diff --git a/src/ui/widget.c b/src/ui/widget.c
index cedda461..28c34ccf 100644
--- a/src/ui/widget.c
+++ b/src/ui/widget.c
@@ -1961,7 +1961,8 @@ iBool isAffectedByVisualOffset_Widget(const iWidget *d) {
 }
 
 void setFocus_Widget(iWidget *d) {
-    iWindow *win = get_Window();
+    iWindow *win = d ? window_Widget(d) : get_Window();
+    iAssert(win);
     if (win->focus != d) {
         if (win->focus) {
             iAssert(!contains_PtrSet(win->focus->root->pendingDestruction, win->focus));
@@ -1976,6 +1977,13 @@ void setFocus_Widget(iWidget *d) {
     }
 }
 
+void setKeyboardGrab_Widget(iWidget *d) {
+    iWindow *win = d ? window_Widget(d) : get_Window();
+    iAssert(win);
+    win->focus = d;
+    /* no notifications sent */
+}
+
 iWidget *focus_Widget(void) {
     return get_Window()->focus;
 }
diff --git a/src/ui/widget.h b/src/ui/widget.h
index 4025f5c5..57088c07 100644
--- a/src/ui/widget.h
+++ b/src/ui/widget.h
@@ -302,7 +302,8 @@ void        scrollInfo_Widget           (const iWidget *, iWidgetScrollInfo *inf
 
 int         backgroundFadeColor_Widget  (void);
 
-void        setFocus_Widget         (iWidget *);
+void        setFocus_Widget         (iWidget *); /* widget must be flagged `focusable` */
+void        setKeyboardGrab_Widget  (iWidget *); /* sets focus on any widget */
 iWidget *   focus_Widget            (void);
 void        setHover_Widget         (iWidget *);
 iWidget *   hover_Widget            (void);
Proxy Information
Original URL
gemini://git.skyjake.fi/lagrange/work%2Fv1.8/cdiff/32cbf877ac137b28eb41a9084717707907c02d94
Status Code
Success (20)
Meta
text/gemini; charset=utf-8
Capsule Response Time
67.877956 milliseconds
Gemini-to-HTML Time
0.332612 milliseconds

This content has been proxied by September (ba2dc).