Tibor's Musings

Emacs Bindings in GTK Applications

Emacs offers many functionalities natively; I routinely use it for writing, email, news, chat, programming, web browsing, image viewing, and much more. Sharing the same environment and the same keyboard shortcuts everywhere is good for productivity. However, what if one uses a standalone GTK application such as Chromium or Pidgin? Is it possible to share most of Emacs keyboard shortcuts there as well?

Setting up Emacs key binding theme

The first step is to configure the window desktop environment to use Emacs-like key bindings generally. Depending on the window manager, it can be done in several ways, for example:

  • Gnome2 and GTK-2 apps:

    $ grep gtk-key-theme-name ~/.gtkrc-2.0
    gtk-key-theme-name = "Emacs"
    
  • Gnome3 and GTK-3 apps:

    $ gnome-tweak-tool    # menu "Theme -> Keybinding Theme -> Emacs"
    
  • Xfce:

    $ xfconf-query -c xsettings -p /Gtk/KeyThemeName -s Emacs
    

This will set many useful keyboard shortcuts such as C-a to go to the beginning of line, C-e to go to the end of line, M-f to move forward a word, M-b to move backward a word, etc.

However, not all key bindings are usually covered. For example, I'm used to hitting M-<backspace> frequently, and this keyboard shortcut is not supported out of the box. Can it be added?

Example: Chromium and Pidgin

En guise of example, let's discuss Chromium and Pidgin GTK applications where we would like to make M-<backspace> to delete the word backwards. Let's start by checking which GTK library they are linked to:

$ ldd /usr/bin/pidgin  | grep gtk
     libgtkspell.so.0 => /usr/lib/libgtkspell.so.0 (0x00007f054d4c9000)
     libgtk-x11-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0 (0x00007f054ce87000)
$ ldd /usr/lib/chromium/chromium | grep gtk
     libgtk-x11-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0 (0x00007ffa726bb000)
$ dpkg -S /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
libgtk2.0-0:amd64: /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0

Now let's see which Emacs bindings are configured by default with GTK2 keyboard scheme:

$ cat /usr/share/themes/Emacs/gtk-2.0-key/gtkrc
binding "gtk-emacs-text-entry"
{
  bind "<ctrl>b" { "move-cursor" (logical-positions, -1, 0) }
  bind "<shift><ctrl>b" { "move-cursor" (logical-positions, -1, 1) }
  bind "<ctrl>f" { "move-cursor" (logical-positions, 1, 0) }
  bind "<shift><ctrl>f" { "move-cursor" (logical-positions, 1, 1) }

  bind "<alt>b" { "move-cursor" (words, -1, 0) }
  bind "<shift><alt>b" { "move-cursor" (words, -1, 1) }
  bind "<alt>f" { "move-cursor" (words, 1, 0) }
  bind "<shift><alt>f" { "move-cursor" (words, 1, 1) }

  [...]

  bind "<ctrl>w" { "delete-from-cursor" (word-ends, -1) }

However, there is no binding for backspace:

$ grep -c -i backspace /usr/share/themes/Emacs/gtk-2.0-key/gtkrc
0

Adding a binding for M-<backspace>

Let's edit ~/.gtkrc-2.0 and enter the above <ctrl>w definition also for <alt>BackSpace:

$ cat ~/.gtkrc-2.0
binding "gtk-emacs-text-entry"
{
   bind "<alt>BackSpace" { "delete-from-cursor" (word-ends, -1) }
}

Now, after re-login, the keyboard shortcut M-<backspace> will work perfectly well in Chromium or Pidgin.

This key binding is very useful, as it is often faster to delete the whole word and re-type it back rather than to correct wrong letters one by one individually. If someone has M-<backspace> hard-wired in muscle memory, now the same shortcut can be used regardless of whether one happens to be in Emacs or in Chromium.

Switching off (some) native application bindings

Going further, it is usually a good idea to alter native application key bindings if they conflict with frequent Emacs ones. This is usually customisable inside the given GTK application.

En guise of example, let's take Pidgin. When editing a message, M-f invokes by default a font menu, which is not very useful feature to me. Hence I can use "Ungroup items" to deactivate it; or I can use "Options -> Show Formatting Toolbar" to disable it for good in a persistent manner.

Conclusions

With a few lines of code, Emacs-like key bindings can be added to well-behaved GTK applications such as Chromium or Pidgin, including custom key bindings.

(P.S. When looking for better Emacs-like keyboard productivity experience in GTK applications, it is usually interesting to go even further. E.g. I've been using Vimperator extension for Firefox, Conkeror XULRunner based browser, Vimium extension for Chromium, Edit with Emacs extension for Chromium, etc. These are covered elsewhere in this blog.)