Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I use awesome as a window manager under gnome (debian system) and I made a widget to switch keyboard layout by this code:

-- Keyboard map indicator and changer
    kbdcfg = {}
    kbdcfg.cmd = "setxkbmap"
    kbdcfg.layout = { { "us", "" }, { "ru", "phonetic" } }
    kbdcfg.current = 1  -- us is our default layout
    kbdcfg.widget = widget({ type = "textbox", align = "right" })
    kbdcfg.widget.text = " " .. kbdcfg.layout[kbdcfg.current][1] .. " "
    kbdcfg.switch = function ()
       kbdcfg.current = kbdcfg.current % #(kbdcfg.layout) + 1
       local t = kbdcfg.layout[kbdcfg.current]
       kbdcfg.widget.text = " " .. t[1] .. " "
       os.execute( kbdcfg.cmd .. " " .. t[1] .. " " .. t[2] )

    -- Mouse bindings
        awful.button({ }, 1, function () kbdcfg.switch() end)
-- Alt + Right Shift switches the current keyboard layout
    awful.key({ "Mod1" }, "Shift_R", function () kbdcfg.switch() end),

It works, however there is a serious problem with keyboard behavior. When I switch to ru layout non of my keyboard bindings works. Awesome bindings don't work. For example vim shortcuts don't also work and etc. How I can solve this problem?

share|improve this question
up vote 1 down vote accepted

Your keyboard bindings are not working because your keyboard no longer has those keysyms.

If you want to have, for example, Alt+F do something, then you need "F" in some key. But if you load "ru" alone, then there is no "F" at all (nor any latin letter).

I think, specially when you need to handle multiple layouts, that it is much better to let X11 (through setxkbmap) do the job for you; the way the window managers do it is much more limited as you have discovered.

You may also try, as the awfull widget seems to call setxkbmap, to change "ru" with "ru,us", eg:

kbdcfg.layout = { { "us", "" }, { "ru,us", "phonetic" } }

that way, the "us" layout will be stacked on top of the "ru" one when loaded, and the keysysms of the "us" layout, while still not directly typeable, will be seen by the X11 layer that handles the key bindings.

share|improve this answer

About AwesomeWM, from its FAQ:

You should use keycodes, instead of keynames, like this:

  1. Run xev.
  2. Press "Print" key.
  3. Read the output

    KeyPress event, serial 34, synthetic NO, window 0x1200002,
    root 0x291, subw 0x0, time 1510129, (471,293), root:(472,316),
    state 0x0, keycode **107** (keysym 0xff61, Print), same_screen YES,
  4. Create ~/screenshots, install scrot and add the following to rc.lua:

    awful.key({ }, "#107", function () awful.util.spawn("scrot -e 'mv $f ~/screenshots/ 2>/dev/null'") end),

Now you may test, that you can create screenshots with any keyboard layout.

share|improve this answer
That's just a working example. The point is to use keycodes – igorepst Jul 2 '13 at 19:21

I've just had to tackle the same problem, and the solution listed here didn't work. I eventually found xkb-switch which worked properly with awesome. It has the added bonus of simplified code in the rc.lua file.

-- language switcher
kbdcfg = {}
kbdcfg.cmd = "xkb-switch -n"
kbdcfg.widget = wibox.widget.textbox()

kbdcfg.current = io.popen("xkb-switch"):read("*a")
kbdcfg.switch = function()
    kbdcfg.current = io.popen("xkb-switch"):read("*a")
share|improve this answer

Not sure if it suppose to be comment or not, however: after reading and using @yotam's comment (thanks! you've got my upvote).

I've decided to take it to the next level, by patching xkb-switch to allow both -n and -p flags, and by that making it possible to switch to the next layout and printing it. until merge can be cloned from here.

Now it's possible to make the switcher a little bit cleaner and faster :)

-- Language switcher
kbdcfg = {}
kbdcfg.widget = wibox.widget.textbox()
kbdcfg.switch = function ()
  current_kb = io.popen("xkb-switch -p -n"):read("*a")

Hope it helps someone :)

EDIT: to make setxkbmap to not disturb switching layout by awesome key bindings, use this kind of command to setup your layout:

setxkbmap -layout "us,il" -option ""

That will make sure no extra options are left from previous configuration.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.