Skip to content

Instantly share code, notes, and snippets.

@erichanson1
Last active January 31, 2026 16:49
Show Gist options
  • Select an option

  • Save erichanson1/a8eb318def837a11eaaf0ebde1ca2c5f to your computer and use it in GitHub Desktop.

Select an option

Save erichanson1/a8eb318def837a11eaaf0ebde1ca2c5f to your computer and use it in GitHub Desktop.
Keyboard Mapping in Ubuntu

Swapping Keys on a Keyboard.

I'm based in the UK, and I've installed Ubuntu 25.10 on my MacBookPro13,2 which has a UK Apple Macintosh Keyboard. During Installation, I select my keyboard as "English (UK, Macintosh)" which for the most part works. It correctly maps shift+3 as £ and option+3 as #, "' :; |\ are all mapped correctly. The only two keys that are wrong are ` and § ( which are swapped around ).

My physical keyboard layout looks like image

But Ubuntu thinks it looks like this image

So, how do we go about swapping the keys? ( ~(tilde) and ±(plusminus) )

The most useful post I've found is this explanation from Damko on Medium

The configuration directory /usr/share/X11/xkb can be divided into

  • geometry/ - files that graphically display the keyboard layout
  • symbols/ keycodes/ - files to configure the key mapping and layout
  • rules/ - files to enable the configuration

Firstly, using xev to determine what keycodes are being pressed - when I press the key "§" ( currently mapped to "`" ) and the key "`" ( currently mapped to "§" )

KeyPress event, serial 38, synthetic NO, window 0xa00001,
    root 0x216, subw 0x0, time 1044812, (-264,-266), root:(640,400),
    state 0x0, keycode 94 (keysym 0x60, grave), same_screen YES,
    XLookupString gives 1 bytes: (60) "`"
    XmbLookupString gives 1 bytes: (60) "`"
    XFilterEvent returns: False

KeyPress event, serial 38, synthetic NO, window 0xa00001,
    root 0x216, subw 0x0, time 1067128, (-264,-266), root:(640,400),
    state 0x0, keycode 49 (keysym 0xa7, section), same_screen YES,
    XLookupString gives 2 bytes: (c2 a7) "§"
    XmbLookupString gives 2 bytes: (c2 a7) "§"
    XFilterEvent returns: False

So, keycodes 94 produces a "`" and needs to produce a "§" and 49 produces a "§" and needs to produce a "`"

I use setxbkmap to print out the settings

setxkbmap -print -verbose 10
Setting verbose level to 10
WARNING: Running setxkbmap against an Xwayland server
locale is C
Trying to load rules file ./rules/evdev...
Trying to load rules file /usr/share/X11/xkb/rules/evdev...
Success.
Applied rules from evdev:
rules:      evdev
model:      pc105
layout:     us
Trying to build keymap using the following components:
keycodes:   evdev+aliases(qwerty)
types:      complete
compat:     complete
symbols:    pc+us+inet(evdev)
geometry:   pc(pc105)
xkb_keymap {
	xkb_keycodes  { include "evdev+aliases(qwerty)"	};
	xkb_types     { include "complete"	};
	xkb_compat    { include "complete"	};
	xkb_symbols   { include "pc+us+inet(evdev)"	};
	xkb_geometry  { include "pc(pc105)"	};
};

Looking at the file /usr/share/X11/xkb/keycodes/evdev

default xkb_keycodes "evdev" {
        minimum = 8;
        maximum = 255;

        <TLDE> = 49;
        <AE01> = 10;
...
     <LSGT> = 94;

There are two ways of going about fixing this. See the final solution

Correcting the functionality of the keys

If you just want to correct the functionality of the keys and care less that the Keyboard Layout diagram is wrong then edit the file

cd /usr/share/X11/xkb/symbols
cp gb gb_orig
vi gb

Search for Macintosh and you'll see that we actually swap the TLDE and LSGT keys around. If you swap them back, then you'll get the correct output when you press the key, but the Keyboard Layout diagram ( as shown above ) will become incorrect.

partial alphanumeric_keys
xkb_symbols "mac" {

    include "latin"

    name[Group1]= "English (UK, Macintosh)";

    key <LSGT> {        [         section,       plusminus ]    };
    key <AE02> {        [               2,              at,         EuroSign    ]       };
    key <AE03> {        [               3,        sterling,       numbersign    ]       };
    key <TLDE> {        [           grave,      asciitilde ]    };

    include "level3(ralt_switch)"
    include "level3(enter_switch)"
};

Logging out and back in, is enough to get the keys working correctly

Modifying the geometry for my keyboard

I tried modifying the geometry for my keyboard, but the keyboard layout never changed. I don't know why. It looks like it should be easy to update the geometry file

sudo -s
cd /usr/share/X11/xkb/geometry
cp pc pc_orig
vi pc

Search for "pc105" xkb_geometry "pc105" { Notice that it is divided up into sections. Head down to the section "Alpha" { This section is divided up into Rows. Modify the first row, replacing the TLDE Key with LSGT

    section "Alpha" {
        top= 61;
        row {
            top= 1;
            keys { <LSGT>, <AE01>, <AE02>, <AE03>, <AE04>,
                   <AE05>, <AE06>, <AE07>, <AE08>, <AE09>,
                   <AE10>, <AE11>, <AE12>,
                   { <BKSP>, "BKSP", color="grey20" }
            };
        };

Likewise, modify the fourth row, replacing the LSGT key with TLDE

       row {
           top= 58;
           keys { { <LFSH>, "LFSH", color="grey20" },
                   <TLDE>, <AB01>, <AB02>, <AB03>, <AB04>, <AB05>,
                   <AB06>, <AB07>, <AB08>, <AB09>, <AB10>,
                   { <RTSH>, "RTSH", color="grey20" }
           };
       };

I tried many combinations of rebooting, running the command dpkg-reconfigure keyboard-configuration and none of these worked.

The Final Solution.

To end up with the Keyboard Layout diagram correct, with the keys producing the correct output, then you have to assign the wrong keycodes to TLDE and LSGT (in the keycodes section) and then swap them back ( in the symbols section ).

cd /usr/share/X11/xkb/keycodes
vi evdev

Change the lines with TLDE to map it to 94, and LSGT to make it to 49.

// translation from evdev scancodes to something resembling xfree86 keycodes.

default xkb_keycodes "evdev" {
	minimum = 8;
	maximum = 255;

	<TLDE> = 94;
	<AE01> = 10;
...
	<LFSH> = 50;
	<LSGT> = 49;
	<AB01> = 52;

So now, when you press keycode 49, it is mapped to LSGT, and when you press keycode 94, it is mapped to TLDE If you've edited /usr/share/X11/xkb/symbols/gb then you will need to swap the changes back so, that TLDE is the section key, and LSGT is the tilde key ( in my mind - this is two wrongs making a right! ).

partial alphanumeric_keys
xkb_symbols "mac" {

    include "latin"

    name[Group1]= "English (UK, Macintosh)";

    key <TLDE> {	[         section,       plusminus ]	};
    key <AE02> {	[               2,              at,         EuroSign	]	};
    key <AE03> {	[               3,        sterling,       numbersign	]	};
    key <LSGT> {	[           grave,      asciitilde ]	};

    include "level3(ralt_switch)"
    include "level3(enter_switch)"
};

Now, when you press the keys you will get the correct output, and when you view the keyboard it is correct.

@erichanson1

Copy link
Copy Markdown
Author

Adding a Delete Key ( Right Hand Alt + Backspace ).

I use Thunderbird as an email client, and one of the things that annoys me, is that Thunderbird on Linux, does not let you delete emails using the Backspace Key ( it does on Mac, because the smaller Mac Keyboards - mine included, don't have a Delete Key ).

I noticed however, that Backspace key only has definitions for level 1 ( No Modifier ) and level 2 ( Shift + Key ).
I decided to put the Delete key on Backspace key, for level 3 ( Right-Alt + Key ) and level 4 ( Shift + Right Alt + Key )

My keyboard now looks like
image

To do this, I added the BKSP line to the file /usr/share/X11/xkb/symbols/gb so the mac section now looks like this

partial alphanumeric_keys
xkb_symbols "mac" {
    
    include "latin"

    name[Group1]= "English (UK, Macintosh)";

    key <TLDE> {        [         section,       plusminus ]    };
    key <AE02> {        [               2,              at,         EuroSign    ]       };
    key <AE03> {        [               3,        sterling,       numbersign    ]       };
    key <LSGT> {        [           grave,      asciitilde ]    };
    key <BKSP> {        [       BackSpace,       BackSpace,       Delete,       Delete  ]       };
    
    
    include "level3(ralt_switch)"
    include "level3(enter_switch)"
};  

I tested, and now I can use the Right Option Key + Backspace Key to delete my emails ( and in text editors it works as a delete the character in front of the cursor key as well ).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment