Skip to content

Add vim navigation to the switcher#360

Merged
H3rmt merged 3 commits intoH3rmt:hyprshellfrom
gabrielvincent:feature/vim-like-navigation
Oct 18, 2025
Merged

Add vim navigation to the switcher#360
H3rmt merged 3 commits intoH3rmt:hyprshellfrom
gabrielvincent:feature/vim-like-navigation

Conversation

@gabrielvincent
Copy link
Contributor

Adds vim-style navigation to the switcher

Changes

  • New keybindings: Added vim-style navigation keys (h/j/k/l) for Left/Down/Up/Right movement
  • Grid navigation: Implements 2D grid navigation for Up/Down directions, allowing users to move vertically through windows and
    workspaces
  • API: Replaced boolean reverse field with a Direction enum in SwitchSwitchConfig for clear directional intent
  • Configuration: Added vim_mode boolean option to windows.switch config to enable/disable vim navigation

Behavior

  • Left/Right (h/l/Tab/Shift+Tab): Cycles through items with wrap-around (existing behavior)
  • Up/Down (k/j): Moves vertically in a grid layout based on items_per_row configuration
    • When reaching edges, stops at first/last item instead of wrapping

Configuration

Vim navigation is disabled by default. To enable it, add the following to your config:

switch: (
  modifier: "alt",
  filter_by: [],
  switch_workspaces: false,
  vim_mode: true,# new configuration
),

When vim_mode = false (default), the hjkl keys are ignored. Tab and Shift+Tab navigation works regardless of this setting.

Technical Details

  • Added find_next_client_grid and find_next_workspace_grid functions in crates/windows-lib/src/next.rs
  • Updated key handlers in crates/windows-lib/src/switch/create.rs
  • Navigation mode selection is automatic based on direction (grid for Up/Down, wrap for Left/Right)
  • Migration code updated to set vim_mode: false for configs upgrading from older versions

@H3rmt
Copy link
Owner

H3rmt commented Oct 16, 2025

I think we should just enable it by default.

If anyone doesn't want to use them they just don't. They should not block any functionality so they should be enabled by default.

(If any configs change I copy the old structs and create a migration file converting the old config. This also adds some work as all old versions must be able to be converted to the newest version.)

This is why I either try to combine config changes in one single change to reduce the amount of migrations.

Even if the change just adds a field, previous hyprshell versions don't know this field but think they should be able to parse the config because of the version field not hanging changed.

@H3rmt
Copy link
Owner

H3rmt commented Oct 16, 2025

But the implementation looks good

@H3rmt
Copy link
Owner

H3rmt commented Oct 16, 2025

I also think it would be cool to add arrowkey support if anyone really wants to use it

@gabrielvincent
Copy link
Contributor Author

(If any configs change I copy the old structs and create a migration file converting the old config. This also adds some work as all old versions must be able to be converted to the newest version.)

For that that I should just create a new m3t4 dir with the migrations in config-lib?

@H3rmt
Copy link
Owner

H3rmt commented Oct 17, 2025

(If any configs change I copy the old structs and create a migration file converting the old config. This also adds some work as all old versions must be able to be converted to the newest version.)

For that that I should just create a new m3t4 dir with the migrations in config-lib?

This would be how a new migration would be done. The migrate function would need to adjusted to also migrate all old configs to the new one.

I still think we shouldn't add a config for this, especially not one that is disabled by default but then add the feature to the features list in the readme.

I don't think there is any value in disabling vim keybinds, especially as the vim keybinds in the overview are also enabled by default

@gabrielvincent
Copy link
Contributor Author

I don't think there is any value in disabling vom keybinds, especially as the vim keybinds in the overview are also enabled by default

Yes, I think this makes sense. Alright, I'm going to revert changes to config and include navigation using arrows alongside hjkl.

@H3rmt H3rmt changed the base branch from hyprshell-release to hyprshell October 18, 2025 14:32
@H3rmt H3rmt merged commit cc0797d into H3rmt:hyprshell Oct 18, 2025
@patroza
Copy link

patroza commented Oct 29, 2025

Does it make sense to report issues here? @gabrielvincent
Key bindings often don't work for me until I move my mouse into the switcher window,
which of course is counterproductive for key navigation :)

Input tricks like this don't help:

    follow_mouse = 0 # requires click to focus window (my preference)
    float_switch_override_focus = 0 # rider popups now maintain focus

@gabrielvincent
Copy link
Contributor Author

@patroza Thanks for reporting this issue. I'm unable to reproduce it on my end, so I need some additional information to investigate:

  • Which version of Hyprshell are you running?
  • When you say "often," does this mean the keybindings work intermittently without any discernible pattern?
  • When the keybindings fail (without hovering over the switcher), does this affect all keybindings or only specific ones? If only some, which ones are affected?

Could you please share your Hyprland config? This will help me check if there's a configuration setting that might be causing this behavior.

@patroza
Copy link

patroza commented Oct 29, 2025

  • from source
  • sometimes it works, other times it doesn't
  • all the arrows don't work (I only test arrows)

hypr-config.zip

@gabrielvincent
Copy link
Contributor Author

Thanks for providing the configs. Some follow up questions:

  • Do you use more than one monitor?
  • Do alt+tab and alt+grave work normally even when arrows don't?

@patroza
Copy link

patroza commented Oct 29, 2025

Thanks for providing the configs. Some follow up questions:

  • Do you use more than one monitor?
  • Do alt+tab and alt+grave work normally even when arrows don't?

Letting go of alt tab or alt grave worked always as expected even when the rest of the keys didn't. I did not try letting go of tab and pressing it again etc.

More interestingly, since rebooting after adding hyprshell as autostart of hyprland, I can no longer reproduce the behaviour and in general the switcher seems to behave better..
Before it was kind of behaving more like a regular window, with active/inactive status that also depended on my mouse location etc. now it behaves like an overlay, including darkening background, a thing of it's own. strange.

when I experienced the issues, hyprshell was running from within a terminal in my vscode.

@gabrielvincent
Copy link
Contributor Author

Interesting. I also noticed that Hyprshell sometimes seems to behave like a window. I never had any issues with keybindings, but occasionally the switcher starts appearing with a fade-in animation. I will try to find the root cause for this.

@H3rmt
Copy link
Owner

H3rmt commented Oct 29, 2025

This is a issue with GTK and the exclusive window mode.

I will try to implement some solution into the plugin that forces focus onto the switch window.

I don't know why using the exclusive window mode doesn't work for some people.

Releasing the key is always handled by the plugin but other keybinds are received by the switch window.

@patroza
Copy link

patroza commented Oct 30, 2025

FYI: after a while I'm losing the keyboard nav support, a restart of hyprshell fixes it.
(even in the "good" launch of hyprshell - not acting like a window, and darkening background when opening)

@gabrielvincent
Copy link
Contributor Author

after a while I'm losing the keyboard nav support, a restart of hyprshell fixes it.

This just happened to me. Not sure how, though. alt+tab and alt+grave continue to work normally. I've been unsuccessful in reproducing this. I'm now running Hyprshell in verbose mode. Let's see if I can catch something next time this happens.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants