Skip to content

Add extensible key map to configuration - #248

Open
dopamane wants to merge 3 commits into
cdepillabout:masterfrom
dopamane:dev/dopamane/extensible-keys
Open

Add extensible key map to configuration#248
dopamane wants to merge 3 commits into
cdepillabout:masterfrom
dopamane:dev/dopamane/extensible-keys

Conversation

@dopamane

@dopamane dopamane commented Oct 13, 2024

Copy link
Copy Markdown

Add keys map to TMConfig. #83

Comment thread src/Termonad/Types.hs Outdated
Comment thread src/Termonad/Types.hs Outdated
Comment thread src/Termonad/Types.hs
}

instance Show TMConfig where
show cfg = (show . options) cfg <> (show . hooks) cfg

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cdepillabout Not sure about this. Let me know what you think. Is show used?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's used in the Show instance of TMState'.

@dopamane

Copy link
Copy Markdown
Author

I tested this out on my branch dev/dopamane/extensible-keys-toggle-theme, works great.

@KonstantinDjairo

Copy link
Copy Markdown

I tested this out on my branch dev/dopamane/extensible-keys-toggle-theme, works great.

can you add support for emacs-like keybindings? like we have in xmonad
(example from my config)

myKeys =
  [ (otherModMasks ++ "M-" ++ key, action tag)
  | (tag, key) <- zip workspacen (words "1 2 3 4 5 6 7 8 9 0")
  , (otherModMasks, action) <-
      [ ("z-"  , windows . W.greedyView)
      , ("S-", windows . W.shift)
      , ("C-", windows .copy)
      ]
  ] ++
  [ ("M-d", spawn "rofi -show run")
  , ("M-s", spawn "bash -c dictpopup")
  , ("M-e", runOrRaise "goldendict" (className =? "GoldenDict-ng"))
  , ("M-p", runOrRaise "librewolf" (className =? "librewolf-default"))
  , ("M-S-g", easySwap)
  , ("M-S-c", spawnAndShift "ws8" "qbittorrent")
  , ("M-S-p", runOrRaise "nyxt" (className =? "Nyxt"))
  , ("M-t", withFocused $ windows . W.sink)  -- Toggle float for the focused window
  , ("M-`", runOrRaise "emacsclient -c" (className =? "Emacs"))
  , ("M-a", spawn "emacsclient -c")
  , ("M-S-q", return ())  -- Unbind Mod + Shift + Q, to avoid quiting the wm.
  , ("M-q", kill)  -- Change the keybinding for closing windows to Mod + Q
  , ("M-m", spawn "mpv  --idle")
  , ("M-S-d", spawn "~/.local/bin/recent_journal.py | popup")
  , ("M-r", runOrRaise "~/.local/bin/run_anki.sh" (className =? "Anki"))
  , ("M-g", runOrRaise "foliate" (className =? "com.github.johnfactotum.Foliate"))
  , ("M-S-f", sendToEmptyWorkspace)  -- View an empty workspace
  , ("M-f", viewEmptyWorkspace)  -- View an empty workspace
  , ("M-S-w", spawn "flameshot gui --path=/mnt/Data/mpv-screenshots/screenshots")
  , ("M-w", spawn "~/.local/bin/copy_image.sh")
  , ("M-S-b", spawn "kill -9 $(pgrep mpv)")
  , ("M-v", spawn "maim --select --hidecursor --format=png --quality 1 /tmp/manga/screenshot.png")
  ]

@cdepillabout

Copy link
Copy Markdown
Owner

can you add support for emacs-like keybindings? like we have in xmonad

Do you mean where you can make key bindings that require the user to press, for example, META and SHIFT at the same time as the key?

I believe the Key data type allows this:

data Key = Key
  { keyVal :: !Word32
  , keyMods :: !(Set ModifierType)
  } deriving (Eq, Ord, Show)

I think the ModifierType represents things like the control key, the shift key, the meta key, etc.

@cdepillabout

Copy link
Copy Markdown
Owner

@dopamane Sorry for taking a while to get to this.

I'm somewhat hesitant to introduce an extensible key map like this. I'd ideally like to expose an abstraction to the end-user like in:

Basically, right now Termonad has two types of keyboard shortcuts:

  • Keyboard shortcuts that are triggered by gtk menu actions (like copy and paste).
  • Keyboard shortcuts that aren't triggered by gtk menu actions (like the key map that is currently in this PR).

I'd ideally like to expose some sort of abstraction to end users to be able to configure and set both of these types of keyboard shortcuts.

This PR currently only allows setting keyboard shortcuts that aren't triggered by gtk menu actions, which means we'll have to have some sort of (breaking?) change when introducing a way to for users to also manipulate keyboard shortcuts that are triggered by gtk menu actions.

One thought I had was to potentially just do away with the keyboard shortcuts that aren't triggered by gtk menu actions. One positive(?) side effect of this is that all keyboard shortcuts will be much more discoverable within the UI, since all shortcut actions must be visible in the GTK menu. (Although this does feel unnecessarily limiting.)

On the other hand, not having any way to set keyboard bindings is pretty limiting, and quite surprising to anyone coming from XMonad. There have been multiple people asking for this. So maybe it is a good idea to try to come up with something, even if it isn't perfect. "Don't let perfect be the enemy of good".

@KonstantinDjairo

Copy link
Copy Markdown

@cdepillabout hello, sorry i didn't saw your comment because i didn't got notifications

but basically i worked on something some time ago:
https://git.ajattix.org/hashirama/haskell-examples/src/branch/main/keyPress.hs

it's extremely simplistic , and i bet termonad already has those "primitive" functions for handling key presses?
the thing is, keyModifiers can be implemented by checking the state of a variable (maybe there's a more pure way of doing it?)

the idea is that when a key is pressed , we can know if the precedent was a modifier , if not modifier is provided , then the final result doesn't get "modified".

these days I've been reading the codebase of termonad to get some familiarity with it, i hope i can contribute to it, since i already gained some experience in gi-gtk, but unfortunately i only worked with the gtk4 version of gi-gtk

@KonstantinDjairo

KonstantinDjairo commented Dec 5, 2025

Copy link
Copy Markdown

can you add support for emacs-like keybindings? like we have in xmonad

Do you mean where you can make key bindings that require the user to press, for example, META and SHIFT at the same time as the key?

after some time i've found this:
https://hackage.haskell.org/package/emacs-keys

it identifies the modifier keys nicely:

>>> parseEmacsKeys "M-a"
Right ([Meta],[Keysym 97])

>>> parseEmacsKeys "Return"
Right ([],[Keysym 65293])

>>> parseEmacsKeys "S-a"
Right ([Shift],[Keysym 65])

the keysim can be translated to something that gtk can understand:

parseKeycode :: Word32 -> IO String
parseKeycode keycode = do
    display <- X11.openDisplay ""  -- Open the display (IO Display)
    
    let keycodeW8 = fromIntegral (keycode :: Word32) :: Word8  
    
    keysym <- keycodeToKeysym display keycodeW8 (0 :: CInt)  -- Get keysym from keycode (IO X11.KeySym)
    let toStringCode = keysymToString keysym  
    
    return toStringCode 

also: https://fossies.org/dox/gtk-4.20.3/gdkkeys-x11_8c_source.html#l00274

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