Working on Windows completely without mouse

For a long time I have used Arch Linux with custom scripting around keyboard shortcuts. Applications could be opened and closed, workspaces could be switched and minimized. Many actions could be performed purely by keyboard. Plus, on linux, working mostly in terminal, it was all felt so good. This was not possible on Windows... up till now!

This is a continuation of my infatuation story with the keyboard.

Amun Tech: Blog & historical content

After changing my layout and learning to touch-type at 90WPM

Just a random test on monkeytype, typed while writing the article

The time has come to fully embrace the keyboard and make the mouse redundant.

Windows navigation & workspaces

to facilitate a full control call windows and the choice chosen workspace when using windows desktop system, I have chosen to use an application called glazeWM

GitHub - glzr-io/glazewm: GlazeWM is a tiling window manager for Windows inspired by i3wm.
GlazeWM is a tiling window manager for Windows inspired by i3wm. - glzr-io/glazewm

GlazeWM allows me to manage multiple screens of applications, without hindrance of flailing my hands for special gestures or managing layers of floating windows.

GlazeWM gets dedicated the ALT+modifier button, while ALT alone keeps its power of focusing the ribbon and giving me access to special functions I don't have shortcuted / use rarely.

You can find my GlazeWM configuration at the end of the page!

I've chosen separation of my work into 4 categories:

  1. General operations (file system tasks, rarely used, or specialized software)
  2. Web browsing
  3. Code editing & interactions with remote services (VSCode)
  4. Note taking & messaging

Each one of these categories gets dedicated place on the number line, including placing relevant applications on the task bar

Quick Access ba

If I want to start one of these "most used" applications (like VSCode) in its dedicated workspace, all I have to do is go [ALT+2] to select the relevant workspace & [Win+2] to start the application. SO FAST!

If I decide to start some other application, all I need is to press the Windows key once, to open the search menu and type away the name of needed program!

I have opened my favorite application, but... I don't know any hotkeys. Is this where keyboard magic ends?

VSCode

VSCode is such a popular and extensively developed application, that it is FULL of accessibility functions, which are going to help us get everything done with our keyboard.

FIRST off, I am going to install an AutoHide KB extension, which is going to make my coding experience more "ZEN"

GitHub - kvoon3/vscode-autohide-kb: Auto hide VSCode sidebar, panel and notifications.
Auto hide VSCode sidebar, panel and notifications. - kvoon3/vscode-autohide-kb

To make the best use of this tool. I am going to put the Advanced Search & File Explorer tools into the Auxiliary Side Panel and in the AutoHideKB, I am going to make that panel hide automatically. If I need these panels, I have Advanced Search under [CTRL+SHIFT+F] and File Explorer under [CTRL+SHIFT+E] for quick action and closure.

While other applications that I might need more persistent, are going to be placed in the main side panel, which I am going to make manually hideable (Pinned) with [CTRL+B].

Bottom panel (terminal & debug views) are also going to be made manually toggleable with [CTRL+~].

VSCode Hotkeys

Next, I am going to set some Custom Hotkeys, for rapid access to all the functions I need:

  • Remove all binds to focus Nth Editor Group . I rarely have more than 2 groups open, so... this is a waste
  • Bind all [CTRL+Num] to openEditorAtIndex options.
    • Now we have ALT+Num for switching system workspaces and CTRL+Num to switch between open files in editor!
  • Facilitate switching between groups with [ALT+ArrowKeys] by editing Focus Editor Group options into [ALT+ArrowKey]
    • Moving files between groups can be set to [ALT+SHIFT+Arrowkeys] by editing Move Editor Into Group hotkeys
      • Remove Copy line down & Copy line up keybinds, when using this functionality
    • Now [CTRL+Tab] can be bound to a more appropriate Focus Next Editor Group
      • Then remove Quick Open Last recently used editor bind

And now for the most fun options:

  • [CTRL+SHIFT+P] for access to typed commands
  • [CTRL+P] for quick access to recent files & file search (works like macos Spotlight)
  • [CTRL+R] to switch between recent workspaces (great for rapidly SSHing to previously used machines)

Chrome (Chromium)

Recently, there was this amazing extension shared in the Chrome Web Store called BrowseCut | Navigate Faster with Keyboard Hotkeys.

And it is EVERYTHING that one could want from keyboard based navigation

BrowseCut | Navigate Faster with Keyboard Hotkeys & Vim Chrome Shortcuts - Chrome Web Store
Cut time browsing. Just type to click links and navigate. Be productive, prevent RSI, stay in flow with smart shortcuts.

You either start typing the text you see in the link, or press / [Slash] to be presented with a screen of Two letter words, which are going to help you select any link or input field.

Done with typing, or want to select some different field while Focus is in an input field? Press ESC!

Navigation around the chrome window is also pretty easy.

  • [CTRL+SHIFT+TAB] Switch tabs
  • [CTRL + SHIFT+ 1...9 ] Switch Tabs
  • [CTRL + T] Open New Tab
  • [CTRL + W] Close Tab
  • [CTRL + SHIFT + T] Reopen Closed Tab
  • [CTRL + SHIFT + A] Search through open Tabs
  • [CTRL + R] Reload Page
  • [ALT + LEFT_ARROW or RIGHT_ARROW ] Go Back / Forward
  • [CTRL+L] Focus address ribbon
  • [CTRL+K] Focus address ribbon and start search
  • [ALT] Focus top bar (e.g. To interact with a Plugin, like Password manager)

With these options, I no longer have to use the keyboard while browsing... at all!

Disabling BrowseCut on chosen websites

When you enter a website on which you want to maintain native navigation & want to stop BrowseCut from interfering. Open that website & click the plugin icon on the top bar.

Obsidian Editor

Also Obsidian has plenty of shortcuts, which are going to help us navigate through the files.

I have special love in my heart for the Omnisearch plugin, which allows me to search for any file, by its title or contents, using [CTRL+R] or to search just in currently open file, using [CTRL+F].

GitHub - scambier/obsidian-omnisearch: A search engine that “just works” for Obsidian. Supports OCR and PDF indexing.
A search engine that “just works” for Obsidian. Supports OCR and PDF indexing. - scambier/obsidian-omnisearch

If I want to manually browse through my vault, I have the Quick Explorer plugin. Which I can quickly open with [CTRL+P] and look through contents of my entire vault, using only keyboard!

GitHub - pjeby/quick-explorer: Perform file explorer operations (and see your current file path) from the Obsidian.md title bar
Perform file explorer operations (and see your current file path) from the Obsidian.md title bar - pjeby/quick-explorer

And, for extra discoverability and testing of the available options, there is always the Key Promoter plugin, which is going to notify you, which keyboard shortcuts could accomplish the task you've just done by mouse.

GOOD LUCK!

Bonus - Voice typing

I LOVE Voice Typing. Dictation requires much less work than typing individual letters on a keyboard, it is BLAZINGLY fast compared to typing and gives us a chance to practice vocalizing our thoughts, instead of limiting our communication abilities to keyboard wars.

Since Windows 10, online voice recognition is very well integrated into the system. All we need to do is:

  • Enable Online Speech Recognition in Settings
  • Press Win+H any time we want to dictate

Windows automatically chooses our main sound input device for this task. AMAZING.

Configurations

GlazeWM

Take note, that I am using a custom ColemakDH.programmer keyboard layout. It not only shuffles positions of buttons, but also gives special characters priority over numbers!

general:
  # Commands to run when the WM has started. This is useful for running a
  # script or launching another application.
  # Example: The below command launches Zebar.
  #startup_commands: ['shell-exec zebar']

  # Commands to run just before the WM is shutdown.
  # Example: The below command kills Zebar.
  #shutdown_commands: ['shell-exec taskkill /IM zebar.exe /F']

  # Commands to run after the WM config is reloaded.
  config_reload_commands: []

  # Whether to automatically focus windows underneath the cursor.
  focus_follows_cursor: false

  # Whether to switch back and forth between the previously focused
  # workspace when focusing the current workspace.
  toggle_workspace_on_refocus: false

  cursor_jump:
    # Whether to automatically move the cursor on the specified trigger.
    enabled: true

    # Trigger for cursor jump:
    # - 'monitor_focus': Jump when focus changes between monitors.
    # - 'window_focus': Jump when focus changes between windows.
    trigger: 'window_focus'

  # How windows should be hidden when switching workspaces.
  # - 'cloak': Recommended. Hides windows with no animation.
  # - 'hide': Legacy method (v3.5 and earlier) that has a brief animation,
  # but has stability issues with some apps.
  hide_method: 'cloak'

  # Affects which windows get shown in the native Windows taskbar. Has no
  # effect if `hide_method: 'hide'`.
  # - 'true': Show all windows (regardless of workspace).
  # - 'false': Only show windows from the currently shown workspaces.
  show_all_in_taskbar: false

gaps:
  # Whether to scale the gaps with the DPI of the monitor.
  scale_with_dpi: true

  # Gap between adjacent windows.
  inner_gap: '5px'

  # Gap between windows and the screen edge.
  outer_gap:
    top: '5px'
    right: '5px'
    bottom: '5px'
    left: '5px'

window_effects:
  # Visual effects to apply to the focused window.
  focused_window:
    # Highlight the window with a colored border.
    # ** Exclusive to Windows 11 due to API limitations.
    border:
      enabled: true
      color: '#8dbcff'

    # Remove the title bar from the window's frame. Note that this can
    # cause rendering issues for some applications.
    hide_title_bar:
      enabled: false

    # Change the corner style of the window's frame.
    # ** Exclusive to Windows 11 due to API limitations.
    corner_style:
      enabled: false
      # Allowed values: 'square', 'rounded', 'small_rounded'.
      style: 'square'

    # Change the transparency of the window.
    transparency:
      enabled: true
      # Can be something like '95%' or '0.95' for slightly transparent windows.
      # '0' or '0%' is fully transparent (and, by consequence, unfocusable).
      opacity: '100%'

  # Visual effects to apply to non-focused windows.
  other_windows:
    border:
      enabled: true
      color: '#a1a1a1'
    hide_title_bar:
      enabled: false
    corner_style:
      enabled: false
      style: 'square'
    transparency:
      enabled: true
      opacity: '90%'

window_behavior:
  # New windows are created in this state whenever possible.
  # Allowed values: 'tiling', 'floating'.
  initial_state: 'tiling'

  # Sets the default options for when a new window is created. This also
  # changes the defaults for when the state change commands, like
  # `set-floating`, are used without any flags.
  state_defaults:
    floating:
      # Whether to center floating windows by default.
      centered: true

      # Whether to show floating windows as always on top.
      shown_on_top: false

    fullscreen:
      # Maximize the window if possible. If the window doesn't have a
      # maximize button, then it'll be fullscreen'ed normally instead.
      maximized: false

      # Whether to show fullscreen windows as always on top.
      shown_on_top: false

workspaces:
  - name: '1'
  - name: '2'
  - name: '3'
  - name: '4'
  - name: '5'
  - name: '6'
  - name: '7'
  - name: '8'
  - name: '9'

window_rules:
  - commands: ['ignore']
    match:
      # Ignores any Zebar windows.
      #- window_process: { equals: 'zebar' }

      # Ignores picture-in-picture windows for browsers.
      - window_title: { regex: '[Pp]icture.in.[Pp]icture' }
        window_class: { regex: 'Chrome_WidgetWin_1|MozillaDialogClass' }

      # Ignore rules for various 3rd-party apps.
      - window_process: { equals: 'PowerToys' }
        window_class: { regex: 'HwndWrapper\[PowerToys\.PowerAccent.*?\]' }
      - window_process: { equals: 'PowerToys' }
        window_title: { regex: '.*? - Peek' }
      - window_process: { equals: 'Lively' }
        window_class: { regex: 'HwndWrapper' }

binding_modes:
  # When enabled, the focused window can be resized via arrow keys or HJKL.
  - name: 'resize'
    keybindings:
      - commands: ['resize --width -2%']
        bindings: ['n', 'left']
      - commands: ['resize --width +2%']
        bindings: ['o', 'right']
      - commands: ['resize --height +2%']
        bindings: ['i', 'up']
      - commands: ['resize --height -2%']
        bindings: ['e', 'down']
      # Press enter/escape to return to default keybindings.
      - commands: ['wm-disable-binding-mode --name resize']
        bindings: ['escape', 'enter']

keybindings:
  # Shift focus in a given direction.
  - commands: ['focus --direction left']
    bindings: ['alt+j']
  - commands: ['focus --direction right']
    bindings: ['alt+oem_semicolon']
  - commands: ['focus --direction up']
    bindings: ['alt+l']
  - commands: ['focus --direction down']
    bindings: ['alt+k']

  # Move focused window in a given direction.
  - commands: ['move --direction left']
    bindings: ['alt+shift+j']
  - commands: ['move --direction right']
    bindings: ['alt+shift+oem_semicolon']
  - commands: ['move --direction up']
    bindings: ['alt+shift+l']
  - commands: ['move --direction down']
    bindings: ['alt+shift+k']

  # Resize focused window by a percentage or pixel amount.
  - commands: ['resize --width -2%']
    bindings: ['alt+u']
  - commands: ['resize --width +2%']
    bindings: ['alt+p']
  - commands: ['resize --height +2%']
    bindings: ['alt+o']
  - commands: ['resize --height -2%']
    bindings: ['alt+i']
  

  # As an alternative to the resize keybindings above, resize mode enables
  # resizing via arrow keys or HJKL. The binding mode is defined above with
  # the name 'resize'.
  - commands: ['wm-enable-binding-mode --name resize']
    bindings: ['alt+r']

  # Disables window management and all other keybindings until alt+shift+p
  # is pressed again.
  - commands: ['wm-toggle-pause']
    bindings: ['alt+shift+p']

  # Change tiling direction. This determines where new tiling windows will
  # be inserted.
  - commands: ['toggle-tiling-direction']
    bindings: ['alt+v']

  # Change focus from tiling windows -> floating -> fullscreen.
  - commands: ['wm-cycle-focus']
    bindings: ['alt+space']

  # Change the focused window to be floating.
  - commands: ['toggle-floating --centered']
    bindings: ['alt+shift+space']

  # Change the focused window to be tiling.
  - commands: ['toggle-tiling']
    bindings: ['alt+t']

  # Change the focused window to be fullscreen.
  - commands: ['toggle-fullscreen']
    bindings: ['alt+f']

  # Minimize focused window.
  - commands: ['toggle-minimized']
    bindings: ['alt+m']

  # Close focused window.
  - commands: ['close']
    bindings: ['alt+q']

  # Kill GlazeWM process safely.
  - commands: ['wm-exit']
    bindings: ['alt+shift+e']

  # Re-evaluate configuration file.
  - commands: ['wm-reload-config']
    bindings: ['alt+shift+r']

  # Redraw all windows.
  - commands: ['wm-redraw']
    bindings: ['alt+shift+w']

  # Launch CMD terminal. Alternatively, use `shell-exec wt` or
  # `shell-exec %ProgramFiles%/Git/git-bash.exe` to start Windows
  # Terminal and Git Bash respectively.
  #- commands: ['shell-exec cmd']
  #  bindings: ['alt+enter']

  # Focus the next/previous active workspace defined in `workspaces` config.
  #- commands: ['focus --next-active-workspace']
  #  bindings: ['alt+s']
  #- commands: ['focus --prev-active-workspace']
  #  bindings: ['alt+a']

  # Focus the workspace that last had focus.
  - commands: ['focus --recent-workspace']
    bindings: ['alt+d']

  # Change focus to a workspace defined in `workspaces` config.
  - commands: ['focus --workspace 1']
    bindings: ['alt+1']
  - commands: ['focus --workspace 2']
    bindings: ['alt+2']
  - commands: ['focus --workspace 3']
    bindings: ['alt+3']
  - commands: ['focus --workspace 4']
    bindings: ['alt+4']
  - commands: ['focus --workspace 5']
    bindings: ['alt+5']
  - commands: ['focus --workspace 6']
    bindings: ['alt+6']
  - commands: ['focus --workspace 7']
    bindings: ['alt+7']
  - commands: ['focus --workspace 8']
    bindings: ['alt+8']
  - commands: ['focus --workspace 9']
    bindings: ['alt+9']

  # Move the focused window's parent workspace to a monitor in a given
  # direction.
  - commands: ['move-workspace --direction left']
    bindings: ['alt+shift+u']
  - commands: ['move-workspace --direction right']
    bindings: ['alt+shift+p']
  - commands: ['move-workspace --direction up']
    bindings: ['alt+shift+o']
  - commands: ['move-workspace --direction down']
    bindings: ['alt+shift+i']

  # Move focused window to a workspace defined in `workspaces` config.
  - commands: ['move --workspace 1', 'focus --workspace 1']
    bindings: ['alt+shift+1']
  - commands: ['move --workspace 2', 'focus --workspace 2']
    bindings: ['alt+shift+2']
  - commands: ['move --workspace 3', 'focus --workspace 3']
    bindings: ['alt+shift+3']
  - commands: ['move --workspace 4', 'focus --workspace 4']
    bindings: ['alt+shift+4']
  - commands: ['move --workspace 5', 'focus --workspace 5']
    bindings: ['alt+shift+5']
  - commands: ['move --workspace 6', 'focus --workspace 6']
    bindings: ['alt+shift+6']
  - commands: ['move --workspace 7', 'focus --workspace 7']
    bindings: ['alt+shift+7']
  - commands: ['move --workspace 8', 'focus --workspace 8']
    bindings: ['alt+shift+8']
  - commands: ['move --workspace 9', 'focus --workspace 9']
    bindings: ['alt+shift+9']

VSCode

[
    {
        "key": "alt+k",
        "command": "-keybindings.editor.recordSearchKeys",
        "when": "inKeybindings && inKeybindingsSearch"
    },
    {
        "key": "alt+k",
        "command": "-editor.action.accessibilityHelpConfigureKeybindings",
        "when": "accessibilityHelpIsShown && accessibleViewHasUnassignedKeybindings"
    },
    {
        "key": "alt+l alt+c",
        "command": "-fiveServer.close",
        "when": "editorTextFocus"
    },
    {
        "key": "alt+l alt+o",
        "command": "-fiveServer.start",
        "when": "editorTextFocus"
    },
    {
        "key": "alt+l",
        "command": "-toggleSearchEditorContextLines",
        "when": "inSearchEditor"
    },
    {
        "key": "alt+l",
        "command": "-toggleFindInSelection",
        "when": "editorFocus"
    },
    {
        "key": "ctrl+shift+oem_2",
        "command": "editor.action.blockComment",
        "when": "editorTextFocus && !editorReadonly"
    },
    {
        "key": "shift+alt+a",
        "command": "-editor.action.blockComment",
        "when": "editorTextFocus && !editorReadonly"
    },
    {
        "key": "ctrl+shift+oem_2",
        "command": "-github.copilot.acceptCursorComparisonPanelSolution",
        "when": "github.copilot.comparisonPanelEnabled && github.copilot.comparisonPanelVisible && activeWebviewPanelId == 'GitHub Copilot Comparison'"
    },
    {
        "key": "ctrl+1",
        "command": "-workbench.action.focusFirstEditorGroup"
    },
    {
        "key": "ctrl+8",
        "command": "-workbench.action.focusEighthEditorGroup"
    },
    {
        "key": "ctrl+5",
        "command": "-workbench.action.focusFifthEditorGroup"
    },
    {
        "key": "ctrl+4",
        "command": "-workbench.action.focusFourthEditorGroup"
    },
    {
        "key": "ctrl+2",
        "command": "-workbench.action.focusSecondEditorGroup"
    },
    {
        "key": "ctrl+7",
        "command": "-workbench.action.focusSeventhEditorGroup"
    },
    {
        "key": "ctrl+6",
        "command": "-workbench.action.focusSixthEditorGroup"
    },
    {
        "key": "ctrl+3",
        "command": "-workbench.action.focusThirdEditorGroup"
    },
    {
        "key": "ctrl+1",
        "command": "workbench.action.openEditorAtIndex1"
    },
    {
        "key": "alt+1",
        "command": "-workbench.action.openEditorAtIndex1"
    },
    {
        "key": "ctrl+2",
        "command": "workbench.action.openEditorAtIndex2"
    },
    {
        "key": "alt+2",
        "command": "-workbench.action.openEditorAtIndex2"
    },
    {
        "key": "ctrl+3",
        "command": "workbench.action.openEditorAtIndex3"
    },
    {
        "key": "alt+3",
        "command": "-workbench.action.openEditorAtIndex3"
    },
    {
        "key": "ctrl+4",
        "command": "workbench.action.openEditorAtIndex4"
    },
    {
        "key": "alt+4",
        "command": "-workbench.action.openEditorAtIndex4"
    },
    {
        "key": "ctrl+5",
        "command": "workbench.action.openEditorAtIndex5"
    },
    {
        "key": "alt+5",
        "command": "-workbench.action.openEditorAtIndex5"
    },
    {
        "key": "ctrl+6",
        "command": "workbench.action.openEditorAtIndex6"
    },
    {
        "key": "alt+6",
        "command": "-workbench.action.openEditorAtIndex6"
    },
    {
        "key": "ctrl+7",
        "command": "workbench.action.openEditorAtIndex7"
    },
    {
        "key": "alt+7",
        "command": "-workbench.action.openEditorAtIndex7"
    },
    {
        "key": "ctrl+8",
        "command": "workbench.action.openEditorAtIndex8"
    },
    {
        "key": "alt+8",
        "command": "-workbench.action.openEditorAtIndex8"
    },
    {
        "key": "ctrl+9",
        "command": "workbench.action.openEditorAtIndex9"
    },
    {
        "key": "alt+9",
        "command": "-workbench.action.openEditorAtIndex9"
    },
    {
        "key": "ctrl+tab",
        "command": "-workbench.action.quickOpenPreviousRecentlyUsedEditorInGroup",
        "when": "!activeEditorGroupEmpty"
    },
    {
        "key": "alt+up",
        "command": "workbench.action.focusAboveGroup"
    },
    {
        "key": "ctrl+k ctrl+up",
        "command": "-workbench.action.focusAboveGroup"
    },
    {
        "key": "alt+down",
        "command": "workbench.action.focusBelowGroup"
    },
    {
        "key": "ctrl+k ctrl+down",
        "command": "-workbench.action.focusBelowGroup"
    },
    {
        "key": "alt+left",
        "command": "workbench.action.focusLeftGroup"
    },
    {
        "key": "ctrl+k ctrl+left",
        "command": "-workbench.action.focusLeftGroup"
    },
    {
        "key": "ctrl+alt+right",
        "command": "workbench.action.focusRightGroup"
    },
    {
        "key": "ctrl+k ctrl+right",
        "command": "-workbench.action.focusRightGroup"
    },
    {
        "key": "ctrl+alt+right",
        "command": "-workbench.action.moveEditorToNextGroup"
    },
    {
        "key": "shift+alt+1",
        "command": "-workbench.action.moveEditorToFirstGroup"
    },
    {
        "key": "shift+alt+9",
        "command": "-workbench.action.moveEditorToLastGroup"
    },
    {
        "key": "ctrl+alt+left",
        "command": "-workbench.action.moveEditorToPreviousGroup"
    },
    {
        "key": "ctrl+k down",
        "command": "-workbench.action.moveActiveEditorGroupDown"
    },
    {
        "key": "ctrl+k left",
        "command": "-workbench.action.moveActiveEditorGroupLeft"
    },
    {
        "key": "ctrl+k right",
        "command": "-workbench.action.moveActiveEditorGroupRight"
    },
    {
        "key": "ctrl+k up",
        "command": "-workbench.action.moveActiveEditorGroupUp"
    },
    {
        "key": "shift+alt+up",
        "command": "workbench.action.moveEditorToAboveGroup"
    },
    {
        "key": "shift+alt+down",
        "command": "workbench.action.moveEditorToBelowGroup"
    },
    {
        "key": "shift+alt+left",
        "command": "workbench.action.moveEditorToLeftGroup"
    },
    {
        "key": "shift+alt+right",
        "command": "workbench.action.moveEditorToRightGroup"
    },
    {
        "key": "ctrl+k ctrl+pagedown",
        "command": "-workbench.action.nextEditorInGroup"
    },
    {
        "key": "ctrl+tab",
        "command": "workbench.action.focusNextGroup"
    },
    {
        "key": "shift+alt+down",
        "command": "-editor.action.copyLinesDownAction",
        "when": "editorTextFocus && !editorReadonly"
    },
    {
        "key": "shift+alt+up",
        "command": "-editor.action.copyLinesUpAction",
        "when": "editorTextFocus && !editorReadonly"
    },
    {
        "key": "ctrl+shift+tab",
        "command": "workbench.action.focusPreviousGroup"
    },
    {
        "key": "ctrl+shift+tab",
        "command": "-workbench.action.quickOpenLeastRecentlyUsedEditorInGroup",
        "when": "!activeEditorGroupEmpty"
    }
]
enplde