Getting your way with setxkbmap

If you’ve ever poked around in the KDE or GNOME control panels, you know that the X11 keyboard system is very customizable and, as the KDE keyboard controls clearly show, that it’s all done using a little command named setxkbmap.

The problem is, Google isn’t very helpful if you want to use this tool directly. All the results seem to tell you to read the raw config files or only give you single, purpose-specific examples.

The good news is that your system actually DOES include a single file equivalent to (and probably the source for) the listings you get in the GUI tools:

/usr/share/X11/xkb/rules/base.lst

For those who haven’t used KDE and need an example, here’s the command I run on login (These can also be specified in xorg.conf via Option directives, but I prefer something I can keep in my roaming profile):

setxkbmap \
  -variant altgr-intl \
  -option \
  -option compose:rctrl \
  -option lv3:ralt_switch \
  -option terminate:ctrl_alt_bkspc \
  -option eurosign:e \
  -option nbsp:level3n

As usual, the backslashes are only necessary if you’re splitting it across multiple lines. Here’s what they actually do when used with a us104 or us105 layout:

-variant altgr-intl
The default variant of the US 104 layout doesn’t have tertiary symbols like ¢ and þ for AltGr to access, so I’m selecting one that does.
You can also use the intl variant here but, for some reason, it maps ² to AltGr+2 and ³ to AltGr+3 but ¹ to AltGr+Shift+1.
-option
An empty -option resets the layout options so I’m starting from a clean slate.
-option compose:rctrl
This remaps the Control_R keysym to Compose, so I can access glyphs like ½, ±, and é by typing “Ctrl 1 2” or “Ctrl + -" or "Ctrl e '“.
-option lv3:ralt_switch
This remaps Alt_R to AltGr, granting access to ¬ (AltGr+\) for making ¬_¬ smileys and giving me simpler key combos for commonly-used glyphs like µ (AltGr+m) and © (AltGr+c).
You can also use ralt_switch_multikey here to make Shift+AltGr the Compose key on compact keyboards but my muscle memory has already settled on Control_R. (Note: Make sure you press Shift first or it’ll just send an ordinary AltGr+Shift)
Note:If anyone knows why ¬ is no longer on AltGr+`, please leave a comment.
-option terminate:ctrl_alt_bkspc
Restore Ctrl+Alt+Backspace as the “Kill X Server” shortcut without relying on a superior but root-privileged and Linux-only config tweak.
(Again, I like settings I can store in my roaming profile)
-option eurosign:e
I’m Canadian, so on the occasions I need to type €, it can take me a while to remember that it has two cross-bars so I know to use “Compose e =“. Since my muscle memory already uses “Compose e '” for é anyway, let’s remap AltGr+e to €.
-option nbsp:level3n
Lets me type non-breaking spaces with AltGr+Space for those times when   doesn’t have special meaning.
Using level3n rather than level3 lets me type thin non-breaking spaces with Shift+AltGr+Space.

The beauty of doing things this way is that you’re unlikely to break things badly. It’s nearly impossible to paint yourself into a corner using variants and options alone (It’s models and layouts you have to be careful with) and, if you ever try to apply your settings to a keyboard they weren’t intended for, an unrecognized variant will abort the process and unrecognized options will simply have no effect.

Have fun and, if you’ve got any other interesting keyboard tweaks, share them in the comments. If I like one that applies to us104 enough to use it myself, I’ll update the example in the post body.

CC BY-SA 4.0 Getting your way with setxkbmap by Stephan Sokolow is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

This entry was posted in Geek Stuff. Bookmark the permalink.

28 Responses to Getting your way with setxkbmap

  1. k2 says:

    I have us104 and not nice and easy PC edition but mac (it’s like 105 but without menu key and grave/tilde changed position with grater/lesser).
    On top of that my native language is polish so i often use ISO level 3.
    To make things even more wild I’m using Emacs a lot.

    So this is my maping:

    I use setxkbmap for swapping caps and control and changing both alt to ISO_level3_shift:
    ctrl:swapcaps,lv3:alt_switch

    i couldn’t figure out how to make setxkbmap do things from benth and things from setxkbmap didn’t work in xmodmap neither

    content of my ~/.Xmodmap:

    ! left corner keyboard wierdo as asciitilde
    keycode 0x5E = grave asciitilde grave asciitilde notsign notsign

    ! keyboard tilde as alt (on the right side of left shift)
    keycode 0x31 = Alt_L Meta_L Alt_L Meta_L

    ! keyboard cmd as alt
    remove Mod4 = Super_R
    keycode 0x86 = Alt_L Meta_L Alt_L Meta_L

    ! register both new alt’s
    add Mod1 = Alt_L Alt_L

  2. rix says:

    Thanks for this one! While playing around, I screwed up and couldn’t use AltGr properly anymore (accidently set it as compose key). Running setxkbmap with an empty -option got everything back to normal.

  3. Pingback: The Telnet Mars » Swapping Control and CapsLock

  4. Good post!!!

    I bought a Perfect Choice small wireless keyboard, the problem is it does not have AltGr Key, ¿how do I map the useless windows key as AltGr? Please help me!

    • First, check what your system sees the desired key as by running “xev” in a terminal and pressing that key.

      Mine sees my right Windows key as “keycode 134 (keysym 0xffec, Super_R)“. If yours doesn’t, you may need to use “xmodmap” to remap it if the following instructions don’t work.

      Second, run “grep lv3: /usr/share/X11/xkb/rules/base.lst” and pick the option for that key. (Internally, X11 refers to AltGr as “Level 3 Shift”)

      Finally, add an appropriate setxkbmap to run at startup in your X11 session. For my example, it would be this:

      setxkbmap -option lv3:rwin_switch

      If you want both Windows keys to be AltGr (rather than leaving one free for making interesting global keyboard shortcuts like Play/Pause), use lv3:win_switch instead.

  5. Pingback: Compose Key on Xfce | The One with the Thoughts of Frans

  6. *Thank you* for writing this post.

    As a dvorak user, it took me some time to get my head wrapped around the concept of models, layouts, and variants. I eventually got my dual-variant working as follows:


    setxkbmap \
    -model pc105 \
    -layout 'us(dvorak-intl),us(alt-intl)' \
    -option \
    -option grp:lctrl_lshift_toggle \
    -option compose:rwin

    I use Ctrl+Shift to toggle between the two variants, so other people can use my keyboard. I am using a 78-key Apple A1314 Bluetooth keyboard on Debian Squeeze.

    Note: it seems like you may omit “-option lv3:ralt_switch” as a parameter, as file /usr/share/X11/xkb/symbols/us , variant “altgr-intl,” seems to call “include “level3(ralt_switch)” to do this as a courtesy.

    Also, re: “Note:If anyone knows why ¬ is no longer on AltGr+`, please leave a comment.”:

    I checked the X.Org repository…the initial 2004-04-10 commit only had basic and intl variants (us layout). At this point, symbol “notsign” mapped to key BKSL (backslash).

    Variant altgr-intl inherits from variant intl. The initial altgr-intl commit did not seem to reference symbol notsign…curious to hear if you found the answer why….

    Thanks again.

    • I’m actually not sure if it was the altgr-intl variant. All I know is that, several years ago, when I was running Gentoo, I was running some kind of keymap which gave me the standard US 104 keyboard layout but put notsign on AltGr+`.

      In fact, now that I think about it, the intl variant would probably have been the first one I tried back then, so the question might actually be “Why did AltGr+1 stop being ¹?”

  7. Frustrated says:

    Why does this work:

    setxkbmap -option caps:backspace

    But this does not:

    setxkbmap -option caps:underscore

    • Because that’s not a valid setxkbmap option. If you look in the file I mentioned (/usr/share/X11/xkb/rules/base.lst), you’ll see that the only valid options beginning with caps: are these:

        caps:internal        Caps Lock uses internal capitalization. Shift "pauses" Caps Lock
        caps:internal_nocancel Caps Lock uses internal capitalization. Shift doesn't affect Caps Lock
        caps:shift           Caps Lock acts as Shift with locking. Shift "pauses" Caps Lock
        caps:shift_nocancel  Caps Lock acts as Shift with locking. Shift doesn't affect Caps Lock
        caps:capslock        Caps Lock toggles normal capitalization of alphabetic characters
        caps:numlock         Make Caps Lock an additional Num Lock
        caps:swapescape      Swap ESC and Caps Lock
        caps:escape          Make Caps Lock an additional ESC
        caps:backspace       Make Caps Lock an additional Backspace
        caps:super           Make Caps Lock an additional Super
        caps:hyper           Make Caps Lock an additional Hyper
        caps:shiftlock       Caps Lock toggles Shift so all keys are affected
        caps:none            Caps Lock is disabled
        caps:ctrl_modifier   Make Caps Lock an additional Control but keep the Caps_Lock keysym
      

      If you want to remap it to an underscore, you can’t use the convenience shortcuts setxkbmap provides.

  8. Steven says:

    Hey, I am new to Linux and am using Xubuntu as well.
    I looked around but can’t seem to understand this no matter how hard I try.
    Can you tell me how I could swap esc with the tilde: “~” or “`” key?

    Thanks.

    • That’s a little too non-standard for setxkbmap to have an option for it.

      What you need is Xmodmap. (It lets you change the mappings between the numeric keycodes returned by the keyboard and the keysyms received by applications)

      There are more detailed instructions on the Arch Linux Wiki but the gist of it is:

      First, run xev in a terminal window, press the keys you want to swap, and look at the keycodes and keysyms it reports for them.

      (On my computer, keycode 66 = Caps_Lock and keycode 49 = grave or asciitilde, depending on whether a Shift key is being held.)

      Second, write a ~/.Xmodmap file which assigns the symbol from the first to the code from the second and vice versa.

      For my keyboard, it would look like this:

      keycode 49 = Caps_Lock
      keycode 66 = grave asciitilde

      Third, test whether your desktop automatically runs Xmodmap on login and, if not, add it as one of the programs to be run on login.

      • Steven says:

        Hey man thanks for the reply and thanks for repeating yourself and not asking me to RTFM.
        I am not cut out for that : (
        Thanks!

  9. Bogdan Jerkosovic says:

    On a modern Linux like Ubuntu Precise it is actually /usr/share/X11/xkb/rules/evdev.lst that’s being used by setxkbmap. base.lst is another one of these paste-and-rape decoy files.

    I should also point out that ‘setxkbmap […] -print’ creates stanzas ready for feeding to xkbcomp, and for me these stanzas were not harder to understand than setxkbmap command line options. I ended up not using setxkbmap at all because it seemed like obfuscation rather than abstraction in the end, and http://madduck.net/docs/extending-xkb/ came to the same conclusion.

    I think the main virtue of this setxkbmap spaghetti is the evdev.xml file which was probably meant for some GUI keyboard configurator wallpaper to parse, but I’m being speculative. Anyway I think humans should create an example stanza with ‘setxkbmap […sane options…] -print’, edit _that_ file, and invoke ‘xkbcomp $DISPLAY’ from xinitrc or Xsession or .config/autostart or whatever you use to twiddle new sessions.

  10. Hisao Nakai says:

    Excellent, very useful post.

    I tried to change from a caps:swapescape to a ctrl:swapcaps config, but couldn’t make head or tail of why it wasn’t working till I put a -verbose flag there and saw the hideous mess it had made of combining all my past changes. I didn’t know how to reset it, and this post pointed me to it (using an empty -option) 😀

    Although now that I see it, it’s mentioned in the setxkbmap man page under -option, so I guess it’s a typical RTFM fail :\

  11. Steven Klein Haneveld says:

    Thanks, I seem to understand a little more now.

    It does not seem to work, though.
    My caps-key seems to function as “shiftlock”, as it also capitalizes all keys.

    I would like it to behave normal, als “capslock”, and only capitalize the alfabethic caracters.

    As i understood, i shoud run
    setxkbmap -option caps:capslock

    So i did, but without any result.

    What’s wrong?

    • Did you try setxkbmap -option -option caps:capslock to reset any previous directives?

      Also, setxkbmap -verbose will tell you what state you’re currently in so you can use a bare -option to reset it and then set only the bits you want to keep.

  12. Thank you Stephan, very helpful post. Appreciate you pointing out the symbols file. Cheers.

  13. John Terpack says:

    Can I use this to do something with my FN keys? Xev recognizes the keys, so I know they work. But they all give identical output when I type them in a terminal. I don’t know if that means the OS doesn’t recognize them or if there’s something else going on. But I would like to use the FN keys for various functions… oddly enough.

    • What do you mean by “they all give identical output when I type them in a terminal”? Do you mean with or without xev?

      If they give identical output when pressed outside xev, that’s not surprising for non-standard keys. The terminal doesn’t know what to do with them.

      If they give identical output inside xev, then we’ll need to adjust a lower level of the system so that the differences are visible to X.org.

      Here’s an example of the relevant bits from xev when I press my left and right Windows keys so you know what to look for in xev’s output:

      state 0x50, keycode 133 (keysym 0xffeb, Super_L), same_screen YES,
      state 0x10, keycode 134 (keysym 0xffec, Super_R), same_screen YES,

      If xev is seeing them as different keys, then you want to do one (or both) of these things:

      • Use Xmodmap to change the keycode->keysym mapping to something more useful. (eg. My RF remote appears as a fake keyboard and mouse and I used Xmodmap to redefine two of the buttons to F13 and F14 so they wouldn’t trigger the desktop’s pre-defined behaviours.)
      • Use a global keyboard shortcut tool like xbindkeys or you desktop’s built-in global shortcut control panel to assign actions to them.

      If xev isn’t seeing them as different keys, then I’ll need to know what hardware you have before I can help further. (eg. Before I moved to a mechanical keyboard, I used to have a first-generation Logitech G15 Gaming Keyboard and I had to install g15daemon to get xev to see events from the macro keys.)

      • John Terpack says:

        Sorry, I should have been clearer. Xev reads F1-F12 just as you would expect. But the terminal outputs a tilde for every one of them. I tried using the information from xev to map F4 to a function in my window manager’s config file. It obviously picked up the key press because the cursor changed behavior slightly when I pressed the key. The function didn’t work, but that could be another issue altogether.

        I’m on a laptop, which complicates things from what I understand. The function keys are also the multimedia keys. But, like I said, xev recognizes the function keys when I use the “fn” modifier.

        • Yeah, that’s normal. In fact, on my system, F1 through F4 show nothing in the terminal when I press them, as it should be. (The tilde happens because the system is mis-translating input it doesn’t use.)

          It’s the same sort of thing as with Print Screen and Pause. There is no typable character that those keys represent and you haven’t bound any action to them, so they do nothing. (By contrast, Home and End have no typable characters, but they do have actions bound to them.)

          What do you want them to do?

          • John Terpack says:

            I don’t have uses for all of them at the moment. Although it would be nice to connect PrtSc to my screenshot tool. There’s an odd concept, right?
            I want to connect some of the function keys to a bash script I’m working on. The goal is to have them select sub-directories in my wallpaper directory so that I can choose different “moods” for the changing background. I don’t know if I can use function keys to directly export a value to a variable or if they’d have to call a script that exported. The basic idea is that if I want to look at mountain scenes for a while I press F3. When I get bored staring at mountains through the terminal I can hit F1 and stare at fast cars for a while. It’s just a slightly more focused randomness. I don’t like the contrast of suddenly going from an underwater scene to some bold abstract design. But I also don’t like staring at the same picture for hours or having to jump through hoops to change it when I get bored of it.

            Doing some more research it seems I may have to install xbindkeys to make this happen. I haven’t seen a clear way of doing it with either setxkbmap or xmodmap. Why does it take 17 programs to get a single keyboard to function properly?

          • setxkbmap and xmodmap are needed because, for historical reasons, X11 has two different layers to how it maps raw keycodes (numbers) from the keyboard into names that programs can listen to.

            The reason you need something like xbindkeys is because, once you DO have the key mapped to a name, you still need a program to listen for the key and actually do something in response.

            As for xbindkeys, you probably don’t need it. Most desktops have global hotkey support built in. (For example, in KDE 4, it’s under System Settings > Shortcuts and Gestures > Global Keyboard Shortcuts.)

            As for what you want, it’s not strange at all to bind Print Screen to screenshot-taking. In fact, KDE binds it to “launch KSnapshot” by default.)

            The only tricky part is that you’ll probably want to leave your function keys free for some applications to use. For example, F3 for “Find Next”… so i’d suggest binding to something like Win+F3 instead, since no applications bind to the Windows key as far as I know.)

            As for setting the background, how to do that depends on which desktop you’re running. (Because, for there to be a standard for it, desktop developers would have to think it’s actually a good idea for programs to be able to change your background without asking.)

  14. John Terpack says:

    I don’t technically run a desktop. I’m using the i3 window manager. It is pretty much strictly a window manager. The mechanism for using key bindings via the WM is pretty klunky and it doesn’t seem to accept function keys anyway.

    The script uses feh to display the background. I was calling feh with different arguments for different workspaces from the WM config file. But that just randomly picked an image from a set drectory each time I switched workspaces. So I decided to write a script to do everything I want in a wallpaper-changer. It’s quite a learning experience.

    I hadn’t thought about the fact that some programs use the fn keys. That’s definitely a problem. A quick test in the Kate text editor shows at least four fn keys used for things already. And I’m sure it’s not the only one. I’ll definitely need a modifier. I’m already using the Super key to handle all the functions of the WM. I guess it wouldn’t hurt to use it with the fn keys, if I can. Thanks for the tip.

    • I don’t technically run a desktop. I’m using the i3 window manager. It is pretty much strictly a window manager. The mechanism for using key bindings via the WM is pretty klunky and it doesn’t seem to accept function keys anyway.

      Then, for the purposes of this problem, your desktop could be considered to be a nebulous “homemade” since you pick-and-choose the APIs for binding global hotkeys and setting the desktop background.

      The script uses feh to display the background.

      For my own cobbled-together desktop environments, I actually prefer a tool named Nitrogen over feh because it gives these nice features:

      • If you don’t specify a file on the command-line, it gives you a nice GUI background picker.
      • You can add --save to your command-line when setting backgrounds and then put nitrogen --restore in your startup script.

      (And, for KDE 4.x, I wrote a script to automate the process of extracting properly-positioned rectangles from a multi-monitor background when setting it to force KDE to give the appearance of spanning across all monitors.)

      Since you’re piecing together your desktop from single-purpose bits, you will want something like xbindkeys. However, be aware that I ran across a bug in some desktops’ xbindkeys support which required me to touch ~/.xbindkeys.noauto and then manually add it to my list of auto-started programs.

      So I decided to write a script to do everything I want in a wallpaper-changer. It’s quite a learning experience.

      I actually prefer to do my scripting in Python because I’ve found shell script makes it hard to write clean, robust code. Here are some of the things which make Python a better shell script than Bourne-family shell scripting:

      …plus a ton of other useful stuff in the standard library, like gzip, json, csv, hashlib, tarfile, zipfile, etc.

      (It also has a nice selection of libraries available that let me do things like D-Bus calls and image manipulation directly rather than waiting for a subprocess to start up and shut down for each one.)

      I’m already using the Super key to handle all the functions of the WM. I guess it wouldn’t hurt to use it with the fn keys, if I can. Thanks for the tip.

      No problem. That’s how I do things. Window management and global hotkeys share Win+… so they don’t collide with application-specific shortcuts. (eg. I have my Audacious Media Player set to pull up the “Jump to Song” dialog when I hit Win+J.)

      • John Terpack says:

        Nicely formatted response. Wish I knew the code here to do the same. I don’t see a menu to explain the formatting code though.

        Anyhow, yes, it seems I am building my own desktop of sorts. Primarily because I don’t really like any of the existing ones. The difference between them is mostly cosmetic. I’m actually enjoying picking the various programs myself and trying to make them appear cohesive. I have a very long way to go. It’s especially fun since this is the first tiling WM I’ve used. I doubt I’ll ever go back to a stacking WM now.

        I’ll give Python a look. You’re right about arrays in bash… and that’s a critical part of what I’m working on. I’ve just always considered bash to be the base on which everything else was built. It never occurred to me that it’s just another scripting language. I’m rather new to this level of coding. So I really don’t know the differences between the languages and how one may be more useful for my application than another. I definitely don’t want to spend hours working around the limitations of bash only to discover I could have done it all in three lines with another language.

        As far as feh vs nitrogen, I’m not sure it matters. I know I looked at both when I was sorting out what to use to display the background. I don’t recall with certainty, but I think I chose feh precisely because it had fewer options. That sounds odd, I’m sure. But I was looking for something simply to display the background. All the extra features were just added complexity to worry about. If needed, I can use the script to save and restore the current wallpaper. But that isn’t really a concern I have. If I ever decide to share the script I may add that option in case others want to save their spot.

        • Nicely formatted response. Wish I knew the code here to do the same. I don’t see a menu to explain the formatting code though.

          There used to be instructions below the comment box before WordPress upgraded them away. I’d patch the theme to add them back, but I keep meaning to find time to replace WordPress entirely, so I’m not sure if it’d be worth the effort.

          Basically, WordPress-based blogs allow you to use a safe subset of raw HTML. (I used “blockquote”, “ul”, “li”, “a”, and “code” tags in that post)

          It’s especially fun since this is the first tiling WM I’ve used. I doubt I’ll ever go back to a stacking WM now.

          I’ve been meaning to switch over to a tiling WM but I don’t have time to let my productivity dip while I learn a new set of keybinds completely from scratch. To make up for that, I’ve been planning to write an rc.lua for AwesomeWM which gives me the behaviour I currently enjoy from Kwin plus support for switching into tiling. Then I can slowly wean myself off the stacking paradigm.

          I’ll give Python a look. You’re right about arrays in bash… and that’s a critical part of what I’m working on. I’ve just always considered bash to be the base on which everything else was built. It never occurred to me that it’s just another scripting language. I’m rather new to this level of coding. So I really don’t know the differences between the languages and how one may be more useful for my application than another. I definitely don’t want to spend hours working around the limitations of bash only to discover I could have done it all in three lines with another language.

          It’s getting a little off-topic, so we’ll want to continue this via e-mail, but feel free to ask me about how to accomplish things in Python. (The higher-level, the better)

          In fact, if you want to send me some snippets you’ve written in bash, I’d be happy to show you how they’d look in idiomatic Python.

          As far as feh vs nitrogen, I’m not sure it matters. I know I looked at both when I was sorting out what to use to display the background. I don’t recall with certainty, but I think I chose feh precisely because it had fewer options. That sounds odd, I’m sure. But I was looking for something simply to display the background. All the extra features were just added complexity to worry about.

          Fair enough. I sort of approached it from the opposite direction, starting with Nitrogen handling everything and then scripting changes to what its --restore would do next time I restarted.

Leave a Reply

Your email address will not be published. Required fields are marked *

By submitting a comment here you grant this site a perpetual license to reproduce your words and name/web site in attribution under the same terms as the associated post.       Also, please be aware that non-constructive comments will have their URL field erased before being approved in order to combat SEO spam.