Score:2

Custom layout and variant keyboard in Wayland

af flag

My use

I use a custom QWERTY keyboard for french. It's the QWERTY Lafayette. https://qwerty-lafayette.org/

The problem

In many applications like vscode, my keyboard does not work and remains in qwerty us. So I can't type the characters accessible with AltGr or the accents in French.

Moreover, in gnome settings, I don't see the keyboard created.

My setup

There is on the website page, the Python installer that I used. It works very well.

Here are the contents in my files that it generates and integrates properly /usr/share/X11/xkb/rules/evdev.xml:

    <layout>
      <configItem>
        <name>fr</name>
        <!-- Keyboard indicator for French layouts -->
        <shortDescription>fr</shortDescription>
        <description>French</description>
        <countryList>
          <iso3166Id>FR</iso3166Id>
        </countryList>
        <languageList>
          <iso639Id>fra</iso639Id>
        </languageList>
      </configItem>
      <variantList>
        <variant>
          <configItem>
            <name>nodeadkeys</name>
            <description>French (no dead keys)</description>
          </configItem>
        </variant>
        <variant>
          <configItem>
            <name>oss</name>
            <description>French (alt.)</description>
          </configItem>
        </variant>
        <variant>
          <configItem>
            <name>oss_latin9</name>
            <description>French (alt., Latin-9 only)</description>
          </configItem>
        </variant>
        <variant>
          <configItem>
            <name>oss_nodeadkeys</name>
            <description>French (alt., no dead keys)</description>
          </configItem>
        </variant>
        <variant>
          <configItem>
            <name>latin9</name>
            <description>French (legacy, alt.)</description>
          </configItem>
        </variant>
        <variant>
          <configItem>
            <name>latin9_nodeadkeys</name>
            <description>French (legacy, alt., no dead keys)</description>
          </configItem>
        </variant>
        <variant>
          <configItem>
            <name>bepo</name>
            <description>French (BEPO)</description>
          </configItem>
        </variant>
        <variant>
          <configItem>
            <name>bepo_latin9</name>
            <description>French (BEPO, Latin-9 only)</description>
          </configItem>
        </variant>
        <variant>
          <configItem>
            <name>bepo_afnor</name>
            <description>French (BEPO, AFNOR)</description>
          </configItem>
        </variant>
        <variant>
          <configItem>
            <name>dvorak</name>
            <description>French (Dvorak)</description>
          </configItem>
        </variant>
        <variant>
          <configItem>
            <name>mac</name>
            <description>French (Macintosh)</description>
          </configItem>
        </variant>
        <variant>
          <configItem>
            <name>azerty</name>
            <description>French (AZERTY)</description>
          </configItem>
        </variant>
        <variant>
          <configItem>
            <name>afnor</name>
            <description>French (AZERTY, AFNOR)</description>
          </configItem>
        </variant>
        <variant>
          <configItem>
            <name>bre</name>
            <description>French (Breton)</description>
          </configItem>
        </variant>
        <variant>
          <configItem>
            <name>oci</name>
            <description>Occitan</description>
            <languageList>
              <iso639Id>oci</iso639Id>
            </languageList>
          </configItem>
        </variant>
        <variant>
          <configItem>
            <name>geo</name>
            <description>Georgian (France, AZERTY Tskapo)</description>
            <languageList>
              <iso639Id>kat</iso639Id>
            </languageList>
          </configItem>
        </variant>
        <variant>
          <configItem>
            <name>us</name>
            <description>French (US)</description>
          </configItem>
        </variant>
        <variant type="lafayette">
          <configItem>
            <name>lafayette</name>
            <description>French (Lafayette)</description>
          </configItem>
        </variant>
        <variant type="lafayette">
          <configItem>
            <name>lafayette42</name>
            <description>French (Lafayette42)</description>
          </configItem>
        </variant>
      </variantList>
    </layout>

In /usr/share/X11/xkb/symbols/fr I have this:

// LAFAYETTE::BEGIN


// Project page  : https://github.com/fabi1cazenave/qwerty-lafayette
// Author        : Fabien Cazenave
// Version       : 0.6.1
// Last change   : 2018-04-08
// License       : WTFPL - Do What The Fuck You Want Public License
//
// French (Qwerty-Lafayette)
//
// Base layer + dead key
// ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┲━━━━━━━━━━┓
// │ ~   │ ! ¡ │ @ ‘ │ # ’ │ $ ¢ │ % ‰ │ ^   │ &   │ * ★ │ (   │ )   │ _ – │ + ± ┃          ┃
// │ `   │ 1 „ │ 2 “ │ 3 ” │ 4 £ │ 5 € │ 6   │ 7 | │ 8 ∞ │ 9   │ 0 ° │ - — │ = ≠ ┃ ⌫        ┃
// ┢━━━━━┷━━┱──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┺━━┳━━━━━━━┫
// ┃        ┃ Q   │ W   │ E   │ R ™ │ T   │ Y ¤ │ U   │ I   │ O   │ P ¶ │ « { │ » } ┃       ┃
// ┃ ↹      ┃   æ │   é │   è │   ® │   þ │   ¥ │   ù │   ij │   œ │   § │  ̂ [ │  ̈ ] ┃       ┃
// ┣━━━━━━━━┻┱────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┺┓  ⏎   ┃
// ┃         ┃ A   │ S   │ D   │ F ª │ G   │ H   │ J   │ K   │ L   │  ⃡   │ "   │ |   ┃      ┃
// ┃ ⇬       ┃   à │   ß │   ð │   ſ │   © │   ← │   ↓ │   ↑ │   → │  ⃡ ` │ '   │ \   ┃      ┃
// ┣━━━━━━┳━━┹──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┲━━┷━━━━━┻━━━━━━┫
// ┃      ┃ > ≥ │ Z   │ X   │ C   │ V   │ B   │ N   │ M º │ ; • │ :   │ ? ¿ ┃               ┃
// ┃ ⇧    ┃ < ≤ │   < │   > │   ç │   ŭ │   † │   ñ │   µ │ , · │ . … │ / \ ┃ ⇧             ┃
// ┣━━━━━━┻┳━━━━┷━━┳━━┷━━━━┱┴─────┴─────┴─────┴─────┴─────┴─┲━━━┷━━━┳━┷━━━━━╋━━━━━━━┳━━━━━━━┫
// ┃       ┃       ┃       ┃                                ┃       ┃       ┃       ┃       ┃
// ┃ Ctrl  ┃ super ┃ Alt   ┃ ␣                              ┃ AltGr ┃ super ┃ menu  ┃ Ctrl  ┃
// ┗━━━━━━━┻━━━━━━━┻━━━━━━━┹────────────────────────────────┺━━━━━━━┻━━━━━━━┻━━━━━━━┻━━━━━━━┛
//
// AltGr layer
// ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┲━━━━━━━━━━┓
// │    ̃ │     │   « │   » │    ́ │    ̈ │    ̂ │   ⁷ │   ⁸ │   ⁹ │   ÷ │     │     ┃          ┃
// │    ̀ │   ! │   ( │   ) │   ' │   " │   ^ │   7 │   8 │   9 │   / │     │     ┃ ⌫        ┃
// ┢━━━━━┷━━┱──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┺━━┳━━━━━━━┫
// ┃        ┃   ≠ │     │     │   — │   ± │     │   ⁴ │   ⁵ │   ⁶ │   × │     │     ┃       ┃
// ┃ ↹      ┃   = │   < │   > │   - │   + │     │   4 │   5 │   6 │   * │     │     ┃       ┃
// ┣━━━━━━━━┻┱────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┺┓  ⏎   ┃
// ┃         ┃     │     │     │     │     │     │   ¹ │   ² │   ³ │   − │    ̇ │     ┃      ┃
// ┃ ⇬       ┃   { │   [ │   ] │   } │   / │     │   1 │   2 │   3 │   - │    ́ │     ┃      ┃
// ┣━━━━━━┳━━┹──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┲━━┷━━━━━┻━━━━━━┫
// ┃      ┃     │    ̃ │    ̀ │     │   – │     │     │   ⁰ │     │     │   ¬ ┃               ┃
// ┃ ⇧    ┃     │   ~ │   ` │   | │   _ │   \ │     │   0 │   , │   . │   + ┃ ⇧             ┃
// ┣━━━━━━┻┳━━━━┷━━┳━━┷━━━━┱┴─────┴─────┴─────┴─────┴─────┴─┲━━━┷━━━┳━┷━━━━━╋━━━━━━━┳━━━━━━━┫
// ┃       ┃       ┃       ┃                                ┃       ┃       ┃       ┃       ┃
// ┃ Ctrl  ┃ super ┃ Alt   ┃ ␣                              ┃ AltGr ┃ super ┃ menu  ┃ Ctrl  ┃
// ┗━━━━━━━┻━━━━━━━┻━━━━━━━┹────────────────────────────────┺━━━━━━━┻━━━━━━━┻━━━━━━━┻━━━━━━━┛

partial alphanumeric_keys modifier_keys
xkb_symbols "lafayette" {
    name[group1]= "French (Lafayette)";
    key.type[group1] = "EIGHT_LEVEL";

    // Digits
    key <AE01> {[ 1               , exclam          , U201E           , exclamdown      , exclam          , VoidSymbol      , VoidSymbol      , VoidSymbol      ]}; // 1 ! „ ¡ !
    key <AE02> {[ 2               , at              , U201C           , U2018           , parenleft       , guillemotleft   , VoidSymbol      , VoidSymbol      ]}; // 2 @ “ ‘ ( «
    key <AE03> {[ 3               , numbersign      , U201D           , U2019           , parenright      , guillemotright  , VoidSymbol      , VoidSymbol      ]}; // 3 # ” ’ ) »
    key <AE04> {[ 4               , dollar          , sterling        , cent            , apostrophe      , dead_acute      , VoidSymbol      , VoidSymbol      ]}; // 4 $ £ ¢ ' ´
    key <AE05> {[ 5               , percent         , EuroSign        , U2030           , quotedbl        , dead_diaeresis  , VoidSymbol      , VoidSymbol      ]}; // 5 % € ‰ " ¨
    key <AE06> {[ 6               , asciicircum     , VoidSymbol      , VoidSymbol      , asciicircum     , dead_circumflex , VoidSymbol      , VoidSymbol      ]}; // 6 ^     ^ ^
    key <AE07> {[ 7               , ampersand       , bar             , brokenbar       , 7               , U2077           , VoidSymbol      , VoidSymbol      ]}; // 7 & | ¦ 7 ⁷
    key <AE08> {[ 8               , asterisk        , infinity        , U2605           , 8               , U2078           , VoidSymbol      , VoidSymbol      ]}; // 8 * ∞ ★ 8 ⁸
    key <AE09> {[ 9               , parenleft       , VoidSymbol      , VoidSymbol      , 9               , U2079           , VoidSymbol      , VoidSymbol      ]}; // 9 (     9 ⁹
    key <AE10> {[ 0               , parenright      , degree          , VoidSymbol      , slash           , division        , VoidSymbol      , VoidSymbol      ]}; // 0 ) °   / ÷

    // Letters, first row
    key <AD01> {[ q               , Q               , ae              , AE              , equal           , notequal        , VoidSymbol      , VoidSymbol      ]}; // q Q æ Æ = ≠
    key <AD02> {[ w               , W               , eacute          , Eacute          , less            , lessthanequal   , VoidSymbol      , VoidSymbol      ]}; // w W é É < ≤
    key <AD03> {[ e               , E               , egrave          , Egrave          , greater         , greaterthanequal, VoidSymbol      , VoidSymbol      ]}; // e E è È > ≥
    key <AD04> {[ r               , R               , registered      , trademark       , minus           , emdash          , VoidSymbol      , VoidSymbol      ]}; // r R ® ™ - —
    key <AD05> {[ t               , T               , thorn           , Thorn           , plus            , plusminus       , VoidSymbol      , VoidSymbol      ]}; // t T þ Þ + ±
    key <AD06> {[ y               , Y               , yen             , currency        , VoidSymbol      , VoidSymbol      , VoidSymbol      , VoidSymbol      ]}; // y Y ¥ ¤
    key <AD07> {[ u               , U               , ugrave          , Ugrave          , 4               , U2074           , VoidSymbol      , VoidSymbol      ]}; // u U ù Ù 4 ⁴
    key <AD08> {[ i               , I               , U0133           , U0132           , 5               , U2075           , VoidSymbol      , VoidSymbol      ]}; // i I ij IJ 5 ⁵
    key <AD09> {[ o               , O               , oe              , OE              , 6               , U2076           , VoidSymbol      , VoidSymbol      ]}; // o O œ Œ 6 ⁶
    key <AD10> {[ p               , P               , section         , paragraph       , asterisk        , multiply        , VoidSymbol      , VoidSymbol      ]}; // p P § ¶ * ×

    // Letters, second row
    key <AC01> {[ a               , A               , agrave          , Agrave          , braceleft       , VoidSymbol      , VoidSymbol      , VoidSymbol      ]}; // a A à À {
    key <AC02> {[ s               , S               , ssharp          , U1E9E           , bracketleft     , VoidSymbol      , VoidSymbol      , VoidSymbol      ]}; // s S ß ẞ [
    key <AC03> {[ d               , D               , eth             , Eth             , bracketright    , VoidSymbol      , VoidSymbol      , VoidSymbol      ]}; // d D ð Ð ]
    key <AC04> {[ f               , F               , U017F           , ordfeminine     , braceright      , VoidSymbol      , VoidSymbol      , VoidSymbol      ]}; // f F ſ ª }
    key <AC05> {[ g               , G               , copyright       , VoidSymbol      , slash           , VoidSymbol      , VoidSymbol      , VoidSymbol      ]}; // g G ©   /
    key <AC06> {[ h               , H               , leftarrow       , U21D0           , VoidSymbol      , VoidSymbol      , VoidSymbol      , VoidSymbol      ]}; // h H ← ⇐
    key <AC07> {[ j               , J               , downarrow       , U21D3           , 1               , onesuperior     , VoidSymbol      , VoidSymbol      ]}; // j J ↓ ⇓ 1 ¹
    key <AC08> {[ k               , K               , uparrow         , U21D1           , 2               , twosuperior     , VoidSymbol      , VoidSymbol      ]}; // k K ↑ ⇑ 2 ²
    key <AC09> {[ l               , L               , rightarrow      , U21D2           , 3               , threesuperior   , VoidSymbol      , VoidSymbol      ]}; // l L → ⇒ 3 ³
    key <AC10> {[ ISO_Level3_Latch, ISO_Level3_Latch, grave           , VoidSymbol      , minus           , U2212           , VoidSymbol      , VoidSymbol      ]}; // ` ` `   - −

    // Letters, third row
    key <AB01> {[ z               , Z               , less            , lessthanequal   , asciitilde      , dead_tilde      , VoidSymbol      , VoidSymbol      ]}; // z Z < ≤ ~ ~
    key <AB02> {[ x               , X               , greater         , greaterthanequal, grave           , dead_grave      , VoidSymbol      , VoidSymbol      ]}; // x X > ≥ ` `
    key <AB03> {[ c               , C               , ccedilla        , Ccedilla        , bar             , brokenbar       , VoidSymbol      , VoidSymbol      ]}; // c C ç Ç | ¦
    key <AB04> {[ v               , V               , ubreve          , Ubreve          , underscore      , endash          , VoidSymbol      , VoidSymbol      ]}; // v V ŭ Ŭ _ –
    key <AB05> {[ b               , B               , dagger          , doubledagger    , backslash       , VoidSymbol      , VoidSymbol      , VoidSymbol      ]}; // b B † ‡ \ 
    key <AB06> {[ n               , N               , ntilde          , Ntilde          , VoidSymbol      , VoidSymbol      , VoidSymbol      , VoidSymbol      ]}; // n N ñ Ñ
    key <AB07> {[ m               , M               , mu              , masculine       , 0               , U2070           , VoidSymbol      , VoidSymbol      ]}; // m M µ º 0 ⁰
    key <AB08> {[ comma           , semicolon       , periodcentered  , U2022           , comma           , VoidSymbol      , VoidSymbol      , VoidSymbol      ]}; // , ; · • ,
    key <AB09> {[ period          , colon           , ellipsis        , VoidSymbol      , period          , VoidSymbol      , VoidSymbol      , VoidSymbol      ]}; // . : …   .
    key <AB10> {[ slash           , question        , backslash       , questiondown    , plus            , notsign         , VoidSymbol      , VoidSymbol      ]}; // / ? \ ¿ + ¬

    // Pinky keys
    key <AE11> {[ minus           , underscore      , emdash          , endash          , VoidSymbol      , VoidSymbol      , VoidSymbol      , VoidSymbol      ]}; // - _ — –
    key <AE12> {[ equal           , plus            , notequal        , plusminus       , VoidSymbol      , VoidSymbol      , VoidSymbol      , VoidSymbol      ]}; // = + ≠ ±
    key <AD11> {[ dead_circumflex , guillemotleft   , bracketleft     , braceleft       , VoidSymbol      , VoidSymbol      , VoidSymbol      , VoidSymbol      ]}; // ^ « [ {
    key <AD12> {[ dead_diaeresis  , guillemotright  , bracketright    , braceright      , VoidSymbol      , VoidSymbol      , VoidSymbol      , VoidSymbol      ]}; // ¨ » ] }
    key <AC11> {[ apostrophe      , quotedbl        , VoidSymbol      , VoidSymbol      , dead_acute      , dead_abovedot   , VoidSymbol      , VoidSymbol      ]}; // ' "     ´ ˙
    key <TLDE> {[ grave           , asciitilde      , VoidSymbol      , VoidSymbol      , dead_grave      , dead_tilde      , VoidSymbol      , VoidSymbol      ]}; // ` ~     ` ~
    key <BKSL> {[ backslash       , bar             , VoidSymbol      , VoidSymbol      , VoidSymbol      , VoidSymbol      , VoidSymbol      , VoidSymbol      ]}; // \ |
    key <LSGT> {[ less            , greater         , lessthanequal   , greaterthanequal, VoidSymbol      , VoidSymbol      , VoidSymbol      , VoidSymbol      ]}; // < > ≤ ≥

    // Space bar
    key <SPCE> {[ space           , nobreakspace    , U2019           , U2019           , nobreakspace    , U202F           , VoidSymbol      , VoidSymbol      ]}; //     ’ ’

    // The “OneDeadKey” is an ISO_Level3_Latch, i.e. a “dead AltGr” key:
    // this is the only way to have a multi-purpose dead key with XKB.
    // The real AltGr key is an ISO_Level5_Switch.
    include "level5(ralt_switch)"
};

To finish, I make setxkbmap fr -variant lafayette When I run this command, it tells me to be careful because I am under Wayland. I have no choice to do it, because the keyboard does not appear in the gnome settings.

David avatar
cn flag
Did you try to configure the keyboard IN vscode? https://vscode-docs.readthedocs.io/en/latest/customization/keybindings/#:~:text=Customizing%20Shortcuts,-All%20keyboard%20shortcuts&text=To%20configure%20keyboard%20shortcuts%20the,default%20bindings%20on%20the%20right.
24601 avatar
in flag
I use an English (UK) qwerty keyboard for all my French writing (I live in France) using the compose key (which latches) and then a series of keys to achieve all the French accented and special characters. It works very well without the need for additional keyboard layers.
Archerbob avatar
sy flag
Are you looking for something similar to Gboard that is on Android that allows for one to use a specific keyboard layout but types in another language? Ubuntu has something similar I believe by adding another input in the "Regions and Language" in "Settings"
jessy avatar
af flag
I'm looking for a way to work like I had on xorg before. Normally everything is supposed to be listed in the gnome settings. Maybe in "Regions and Language" I have to change the iBus input by something else. I don't see how to add my variant in "Regions and Language"
Sadaharu Wakisaka avatar
pl flag
Bienvenue à AskUbuntu, you can turn Wayland off and Xorg on, svp.
jessy avatar
af flag
@SadaharuWakisaka Yes I do that, I'm on Xorg, the keyboard works fine. The only problem is the gnome settings, I don't see the keyboard in gnome settings. But I search a more durable solution
Score:1
us flag

Wayland applications don't know what a setxkbmap is. If you're using a GNOME Wayland session, try

gsettings set org.gnome.desktop.input-source "[('xkb', 'fr+lafayette')]"

I'm not sure how you can get GNOME Settings to provide that as a possible choice in the "add input source" dialog. AFAICT gnome-control-center 43 gets those from libgnome-desktop, using gnome_xkb_info_get_layouts_for_language(), which, I think, delegates to libxkbregistry, which was merged into libxkbcommon at some point, which I think is supposed to parse /usr/share/X11/xkb/rules/evdev.xml.

Maybe your evdev.xml is broken? I find it strange to see type="..." on your custom <variant> tags that none of the other tags have.

jessy avatar
af flag
Thanks! I make `gsettings set org.gnome.desktop.input-sources show-all-sources true` and remove the type in variant. It works for the moment
cn flag
The correct command for me was: ``` gsettings set org.gnome.desktop.input-sources sources "[('xkb', 'the_kbd_name')]" ``` (Also, not sure if that's relevant, but I also ran the `show-all-sources` command from @jessy first)
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.