How do I get current keyboard layout?

98,600

Solution 1

Maybe this is version dependent, but on my machine that uses setxkbmap 1.3.0 the following command works:

setxkbmap -query | grep layout

Note that depending on your need it may be useless to know only the layout : for instance the Dvorak variant of the US layout is quite different than the default QWERTY. The -query option of setxkbmap gives both the layout and the variant, as different fields :

$ setxkbmap -query
rules:      evdev
model:      default
layout:     fr
variant:    bepo
options:    grp:alt_shift_toggle

Solution 2

Yes THERE IS a command line tool that does what you want! I just discovered it 10min ago :)

Look at here: https://github.com/nonpop/xkblayout-state

xkblayout-state print "%s"

does exactly what you want (it doesn't output an end of line, so add ; echo if you need). run the tool without parameters for the help.

Solution 3

There is xkb-switch which is described thus:

xkb-switch is a C++ program that allows to query and change the XKB layout state.

https://github.com/ierton/xkb-switch

Or, following nozimica's suggestion, you could use:

setxkbmap -print | awk -F"+" '/xkb_symbols/ {print $2}'

From this thread on the Arch Linux boards: https://bbs.archlinux.org/viewtopic.php?pid=539406

Solution 4

Use this to get the code for the current layout:

$(xset -q|grep LED| awk '{ print $10 }')

This might needs to be converted to a form you want, like:

case "$(xset -q|grep LED| awk '{ print $10 }')" in
  "00000002") KBD="English" ;;
  "00001002") KBD="Thai" ;;
  *) KBD="unknown" ;;
esac

Solution 5

The answers so far did not work for me. I use setkbmap with two layouts english and czech so any -print or -query will always return the two. Grepping the LED status for xset -q does not work either since that one shows the status of all keyboard leds.

The best so far was to quickly write this small utility: https://gist.github.com/fikovnik/ef428e82a26774280c4fdf8f96ce8eeb

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <X11/XKBlib.h>
#include <X11/extensions/XKBrules.h>

int main(int argc, char **argv) {
  Display *dpy = XOpenDisplay(NULL);

  if (dpy == NULL) {
    fprintf(stderr, "Cannot open display\n");
    exit(1);
  }

  XkbStateRec state;
  XkbGetState(dpy, XkbUseCoreKbd, &state);

  XkbDescPtr desc = XkbGetKeyboard(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
  char *group = XGetAtomName(dpy, desc->names->groups[state.group]);
  printf("Full name: %s\n", group);

  XkbRF_VarDefsRec vd;
  XkbRF_GetNamesProp(dpy, NULL, &vd);

  char *tok = strtok(vd.layout, ",");

  for (int i = 0; i < state.group; i++) {
    tok = strtok(NULL, ",");
    if (tok == NULL) {
      return 1;
    }
  }

  printf("Layout name: %s\n", tok);

  return 0;
}

and compile using

gcc -I/usr/include getxkblayout.c -lX11 -lxkbfile

Share:
98,600

Related videos on Youtube

Andrew
Author by

Andrew

Updated on September 18, 2022

Comments

  • Andrew
    Andrew over 1 year

    I'm wondering if there is any command line tool that returns the current keyboard layout.

    I have XkbLayout set to us, ru.

    Update: setxkbmap returns layout settings, not selected layout. E.g.:

    $ setxkbmap -print | grep xkb_symbols
    xkb_symbols   { include "pc+us+ru:2+inet(evdev)+capslock(grouplock)+terminate(ctrl_alt_bksp)"   };
    

    It will return the same result no matter what the current layout is.

    • neydroydrec
      neydroydrec over 12 years
      I am not really good at D-Bus, but it should be easy to track the current keyboard layout using it I think. Although it may not be able to do so if there is no active switch.
  • Andrew
    Andrew about 13 years
    it returns overall keyboard settings, not current layout (us or ru)
  • stefan
    stefan about 13 years
    Execute it well, as @jasonwryan states if you analyze carefully that line, into it resides your layout. In my case it is latam.
  • Andrew
    Andrew about 13 years
    jasonwryan version just output a part of string after '+', xkb_symbols value doesn't depend on selected layout, I always get 'us'
  • Andrew
    Andrew about 13 years
    Thanks, xkb-switch works fine, but I hope that there was more portable solution
  • neydroydrec
    neydroydrec over 12 years
    @Andrew: yes it's kind of odd there is no simple way to get the current layout.
  • l0b0
    l0b0 over 12 years
    I get 00000002 even though my layout is "USA Dvorak international". Language is not enough...
  • sastanin
    sastanin over 11 years
    It doesn't help if there are three or more layouts. The second and the third layouts give the same value 00001004 on my machine.
  • sastanin
    sastanin over 11 years
    It prints only the first layout in the list, not the current one.
  • MusiGenesis
    MusiGenesis about 11 years
    -query was added in setxkbmap 1.2.0
  • xlembouras
    xlembouras almost 10 years
    I like this one, I think you can narrow it down to 8 chars. c59-66.
  • terdon
    terdon over 8 years
    Your setxkbmap doesn't show the currently active layout when more than one layout is defined.
  • erik
    erik about 8 years
    You get the current layouts and variants and many additional info with setxkbmap -print -verbose 10
  • erik
    erik about 8 years
    To set it, for example both layouts cz and us, the latter with variant dvorak (for a 104 key keyboard), use setxkbmap -model pc104 -layout cz,us -variant ,dvorak
  • andras.tim
    andras.tim almost 8 years
    How can I detect my keymap, when I use language toggle by setxkbmap? $ setxkbmap -v >> Trying to build keymap using the following components: | keycodes: evdev+aliases(qwerty) | types: complete | compat: complete+ledscroll(group_lock) | symbols: pc+us+hu:2+inet(evdev)+group(alt_shift_toggle)+compose(rwin)‌​+terminate(ctrl_alt_‌​bksp) | geometry: pc(pc105) in this case I got everytime "us"
  • fikovnik
    fikovnik over 6 years
    This will not work reliably - you need to use a mask since the LED indicates the status of the keyboard led buttons as well.
  • nephewtom
    nephewtom over 4 years
    In which package is XKBrules.h contained? x11proto-dev does not contain it.
  • fikovnik
    fikovnik over 4 years
    @nephewtom libxkbfile
  • xeruf
    xeruf almost 4 years
    doesn't let you know the active one for multiple layouts, which is what the OP asked. Bummer this got to the top.
  • xeruf
    xeruf almost 4 years
    doesn't show the currently active layout when more than one layout is defined, only shows the first
  • invot
    invot over 3 years
    At my side setxkbmap -query | awk '/layout/ {print $2}' gives us,de,us. It does not return the current keyboard layout but gives the available keyboard layouts. And after setxkbmap us the Win+SPC no more toggles to German, so this approach has bad sideffects.
  • invot
    invot over 3 years
    I'd wish there would be some generic solution which "just works"(tm) on any X11 desktop you can imagine, like KDE, GNOME and, say, WubbaLubbaDubDub.
  • ali b
    ali b over 3 years
    @Tino It print those languages because either you (with command setxkbmap -layout us,de) or the system at the startup set it like so. you can put the command setxkbmap <default language> in the startup scripts like .xinitrc or .xprofile to fix it. Afterwards when you query for current keyboard layout, it'll show you one layout. Win+SPC does not work because SPC in German is different character from that in Eng. So when you switch German the combination won't work.So in this way, the best solution is to use a hotkey with non-printable characters like Alt-Esc or Alt-shift etc.
  • Flow
    Flow over 3 years
    This is one of the reasons I don't recommend using xmodmap, use setxkbmap and xkbcomp instead.