diff --git a/data/README.osk-layouts b/data/README.osk-layouts
index a0a0dbea5..88e746e4d 100644
--- a/data/README.osk-layouts
+++ b/data/README.osk-layouts
@@ -55,6 +55,12 @@ it has the following structure:
   - keyval (String): Hexadecimal keyval to emit as
     emulated key presses. Committed strings are
     preferred.
+  - leftOffset (Double): If set, the left offset of
+    this key, relative to the key immediately to the
+    left, or the start of the row. If not set, the key
+    will be implicitly located at the right of the
+    previous key in the row. Multiples of 0.5 are
+    accepted.
   - width (Double): Relative width of the key in the
     row. 1 is for a square key. Multiples of 0.5 are
     accepted.
diff --git a/data/osk-layouts/am.json b/data/osk-layouts/am.json
index 831677447..7830a39a3 100644
--- a/data/osk-layouts/am.json
+++ b/data/osk-layouts/am.json
@@ -121,6 +121,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "ա"
             ]
@@ -384,6 +385,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "Ա"
             ]
@@ -604,6 +606,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -868,6 +871,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
@@ -1048,4 +1052,4 @@
   ],
   "locale": "hy",
   "name": "Armenian"
-}
\ No newline at end of file
+}
diff --git a/data/osk-layouts/ara.json b/data/osk-layouts/ara.json
index 10095ce89..9bdc9bcec 100644
--- a/data/osk-layouts/ara.json
+++ b/data/osk-layouts/ara.json
@@ -151,6 +151,7 @@
         ],
         [
           {
+            "leftOffset": 1,
             "strings": [
               "ذ"
             ]
@@ -335,6 +336,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -603,6 +605,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
@@ -790,4 +793,4 @@
   ],
   "locale": "ar",
   "name": "Arabic"
-}
\ No newline at end of file
+}
diff --git a/data/osk-layouts/at.json b/data/osk-layouts/at.json
index 31715a3ec..d73117412 100644
--- a/data/osk-layouts/at.json
+++ b/data/osk-layouts/at.json
@@ -81,6 +81,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "ä",
@@ -322,6 +323,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "Ä",
@@ -560,6 +562,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -808,6 +811,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/be.json b/data/osk-layouts/be.json
index 6e4f75d5d..3ee92e05a 100644
--- a/data/osk-layouts/be.json
+++ b/data/osk-layouts/be.json
@@ -603,6 +603,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -851,6 +852,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/bg.json b/data/osk-layouts/bg.json
index fb7385deb..c825c9f78 100644
--- a/data/osk-layouts/bg.json
+++ b/data/osk-layouts/bg.json
@@ -538,6 +538,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -786,6 +787,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/by.json b/data/osk-layouts/by.json
index 25543eb6b..e74fe9a6f 100644
--- a/data/osk-layouts/by.json
+++ b/data/osk-layouts/by.json
@@ -548,6 +548,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -796,6 +797,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
@@ -962,4 +964,4 @@
   ],
   "locale": "be",
   "name": "Belarusian"
-}
\ No newline at end of file
+}
diff --git a/data/osk-layouts/ca.json b/data/osk-layouts/ca.json
index 230a6ba93..c19b7b90e 100644
--- a/data/osk-layouts/ca.json
+++ b/data/osk-layouts/ca.json
@@ -96,6 +96,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "à",
@@ -352,6 +353,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "À",
@@ -590,6 +592,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -838,6 +841,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/ch+fr.json b/data/osk-layouts/ch+fr.json
index 1081cc0be..300d937ec 100644
--- a/data/osk-layouts/ch+fr.json
+++ b/data/osk-layouts/ch+fr.json
@@ -81,6 +81,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "ä",
@@ -322,6 +323,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "Ä",
@@ -560,6 +562,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -808,6 +811,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/ch.json b/data/osk-layouts/ch.json
index 1844afabe..2e7a9368d 100644
--- a/data/osk-layouts/ch.json
+++ b/data/osk-layouts/ch.json
@@ -81,6 +81,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "ä",
@@ -322,6 +323,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "Ä",
@@ -560,6 +562,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -808,6 +811,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/cz.json b/data/osk-layouts/cz.json
index 38067de0b..a026d18ab 100644
--- a/data/osk-layouts/cz.json
+++ b/data/osk-layouts/cz.json
@@ -96,6 +96,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "á",
@@ -359,6 +360,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "Á",
@@ -604,6 +606,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -852,6 +855,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/de.json b/data/osk-layouts/de.json
index d41b499ae..0cb1bf1d2 100644
--- a/data/osk-layouts/de.json
+++ b/data/osk-layouts/de.json
@@ -81,6 +81,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "ä",
@@ -322,6 +323,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "Ä",
@@ -560,6 +562,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -808,6 +811,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/dk.json b/data/osk-layouts/dk.json
index fe277ae7b..089e3b8fb 100644
--- a/data/osk-layouts/dk.json
+++ b/data/osk-layouts/dk.json
@@ -594,6 +594,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -842,6 +843,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/ee.json b/data/osk-layouts/ee.json
index 395fbcea3..4c5b59b1d 100644
--- a/data/osk-layouts/ee.json
+++ b/data/osk-layouts/ee.json
@@ -670,6 +670,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -918,6 +919,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/epo.json b/data/osk-layouts/epo.json
index d0da53f9e..ac18c36d5 100644
--- a/data/osk-layouts/epo.json
+++ b/data/osk-layouts/epo.json
@@ -706,6 +706,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -954,6 +955,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/es+cat.json b/data/osk-layouts/es+cat.json
index fab8d4eae..00219c7ad 100644
--- a/data/osk-layouts/es+cat.json
+++ b/data/osk-layouts/es+cat.json
@@ -594,6 +594,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -843,6 +844,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/es.json b/data/osk-layouts/es.json
index 652c07f3a..9c8bf4958 100644
--- a/data/osk-layouts/es.json
+++ b/data/osk-layouts/es.json
@@ -592,6 +592,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -843,6 +844,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/fi.json b/data/osk-layouts/fi.json
index 5a6b7f27b..39d4241c0 100644
--- a/data/osk-layouts/fi.json
+++ b/data/osk-layouts/fi.json
@@ -574,6 +574,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -822,6 +823,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/fr.json b/data/osk-layouts/fr.json
index bf1ba86e4..3267ed833 100644
--- a/data/osk-layouts/fr.json
+++ b/data/osk-layouts/fr.json
@@ -608,6 +608,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -856,6 +857,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/ge.json b/data/osk-layouts/ge.json
index 33884f685..b5f495120 100644
--- a/data/osk-layouts/ge.json
+++ b/data/osk-layouts/ge.json
@@ -66,6 +66,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "ა",
               "ჺ"
@@ -284,6 +285,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A"
             ]
@@ -509,6 +511,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -757,6 +760,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/gr.json b/data/osk-layouts/gr.json
index a60a18619..471e81923 100644
--- a/data/osk-layouts/gr.json
+++ b/data/osk-layouts/gr.json
@@ -72,6 +72,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "α",
               "ά"
@@ -294,6 +295,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "Α",
               "Ά"
@@ -522,6 +524,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -770,6 +773,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/hr.json b/data/osk-layouts/hr.json
index 0b83cdc76..95ff2d880 100644
--- a/data/osk-layouts/hr.json
+++ b/data/osk-layouts/hr.json
@@ -66,6 +66,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a"
             ]
@@ -288,6 +289,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A"
             ]
@@ -522,6 +524,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -770,6 +773,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/hu.json b/data/osk-layouts/hu.json
index f45f31c3c..e686cd78f 100644
--- a/data/osk-layouts/hu.json
+++ b/data/osk-layouts/hu.json
@@ -91,6 +91,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "á",
@@ -337,6 +338,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "Á",
@@ -570,6 +572,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -818,6 +821,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/id.json b/data/osk-layouts/id.json
index 6d57095b2..8eb3fc09d 100644
--- a/data/osk-layouts/id.json
+++ b/data/osk-layouts/id.json
@@ -63,6 +63,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a"
             ]
@@ -273,6 +274,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A"
             ]
@@ -498,6 +500,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -746,6 +749,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/il.json b/data/osk-layouts/il.json
index d797b748c..03f7d521d 100644
--- a/data/osk-layouts/il.json
+++ b/data/osk-layouts/il.json
@@ -125,6 +125,7 @@
         ],
         [
           {
+            "leftOffset": 1,
             "strings": [
               "ז",
               "ז׳"
@@ -298,6 +299,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -547,6 +549,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
@@ -715,4 +718,4 @@
   ],
   "locale": "he",
   "name": "Hebrew"
-}
\ No newline at end of file
+}
diff --git a/data/osk-layouts/in+bolnagri.json b/data/osk-layouts/in+bolnagri.json
index e28063367..a3c0e3043 100644
--- a/data/osk-layouts/in+bolnagri.json
+++ b/data/osk-layouts/in+bolnagri.json
@@ -326,6 +326,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -575,6 +576,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/in+mal.json b/data/osk-layouts/in+mal.json
index 49dcd6b96..3daaf9e1a 100644
--- a/data/osk-layouts/in+mal.json
+++ b/data/osk-layouts/in+mal.json
@@ -568,6 +568,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -817,6 +818,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/ir.json b/data/osk-layouts/ir.json
index eab25bb52..cae9368ad 100644
--- a/data/osk-layouts/ir.json
+++ b/data/osk-layouts/ir.json
@@ -151,6 +151,7 @@
         ],
         [
           {
+            "leftOffset": 1,
             "strings": [
               "ذ"
             ]
@@ -335,6 +336,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "٬",
               "@"
@@ -606,6 +608,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
@@ -794,4 +797,4 @@
   ],
   "locale": "fa",
   "name": "Persian"
-}
\ No newline at end of file
+}
diff --git a/data/osk-layouts/is.json b/data/osk-layouts/is.json
index ac3176cd4..736784f52 100644
--- a/data/osk-layouts/is.json
+++ b/data/osk-layouts/is.json
@@ -92,6 +92,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "á",
@@ -340,6 +341,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "Á",
@@ -574,6 +576,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -822,6 +825,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/it.json b/data/osk-layouts/it.json
index 781aa0f5e..84d68e996 100644
--- a/data/osk-layouts/it.json
+++ b/data/osk-layouts/it.json
@@ -90,6 +90,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "à",
@@ -336,6 +337,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "À",
@@ -570,6 +572,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -818,6 +821,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/ke.json b/data/osk-layouts/ke.json
index 198d6b308..1c16aea28 100644
--- a/data/osk-layouts/ke.json
+++ b/data/osk-layouts/ke.json
@@ -86,6 +86,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "à",
@@ -331,6 +332,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "À",
@@ -568,6 +570,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -816,6 +819,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/kg.json b/data/osk-layouts/kg.json
index 1f806ad0d..d756f25cf 100644
--- a/data/osk-layouts/kg.json
+++ b/data/osk-layouts/kg.json
@@ -554,6 +554,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -802,6 +803,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
@@ -968,4 +970,4 @@
   ],
   "locale": "ky",
   "name": "Kirghiz"
-}
\ No newline at end of file
+}
diff --git a/data/osk-layouts/kh.json b/data/osk-layouts/kh.json
index 78591b518..4ffafb729 100644
--- a/data/osk-layouts/kh.json
+++ b/data/osk-layouts/kh.json
@@ -399,6 +399,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -648,6 +649,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/kr.json b/data/osk-layouts/kr.json
index d89f8c786..ba43e7f3a 100644
--- a/data/osk-layouts/kr.json
+++ b/data/osk-layouts/kr.json
@@ -74,6 +74,7 @@
         [
           {
             "label": "ㅁ",
+            "leftOffset": 0.5,
             "strings": [
               "a"
             ]
@@ -135,6 +136,7 @@
         [
           {
             "label": "ㅋ",
+            "leftOffset": 1,
             "strings": [
               "z"
             ]
@@ -303,6 +305,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -551,6 +554,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/la.json b/data/osk-layouts/la.json
index 65f0feeae..09e1ab82b 100644
--- a/data/osk-layouts/la.json
+++ b/data/osk-layouts/la.json
@@ -389,6 +389,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -638,6 +639,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/latam.json b/data/osk-layouts/latam.json
index 01c67f870..5058c17d5 100644
--- a/data/osk-layouts/latam.json
+++ b/data/osk-layouts/latam.json
@@ -592,6 +592,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -843,6 +844,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/lt.json b/data/osk-layouts/lt.json
index a0f52a5e1..dbfc4bc97 100644
--- a/data/osk-layouts/lt.json
+++ b/data/osk-layouts/lt.json
@@ -102,6 +102,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "ą",
@@ -382,6 +383,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "Ą",
@@ -638,6 +640,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -886,6 +889,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/lv.json b/data/osk-layouts/lv.json
index 2a2dcd124..04cc7e968 100644
--- a/data/osk-layouts/lv.json
+++ b/data/osk-layouts/lv.json
@@ -101,6 +101,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "ā",
@@ -380,6 +381,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "Ā",
@@ -636,6 +638,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -884,6 +887,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/mk.json b/data/osk-layouts/mk.json
index 0c20ead9d..c716f9145 100644
--- a/data/osk-layouts/mk.json
+++ b/data/osk-layouts/mk.json
@@ -548,6 +548,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -796,6 +797,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
@@ -962,4 +964,4 @@
   ],
   "locale": "mk",
   "name": "Macedonian"
-}
\ No newline at end of file
+}
diff --git a/data/osk-layouts/mn.json b/data/osk-layouts/mn.json
index 9cf41f53b..2184a3310 100644
--- a/data/osk-layouts/mn.json
+++ b/data/osk-layouts/mn.json
@@ -552,6 +552,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -801,6 +802,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
@@ -968,4 +970,4 @@
   ],
   "locale": "mn",
   "name": "Mongolian"
-}
\ No newline at end of file
+}
diff --git a/data/osk-layouts/my.json b/data/osk-layouts/my.json
index 1aedf2032..cc23107b0 100644
--- a/data/osk-layouts/my.json
+++ b/data/osk-layouts/my.json
@@ -63,6 +63,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a"
             ]
@@ -273,6 +274,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A"
             ]
@@ -498,6 +500,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -746,6 +749,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/nl.json b/data/osk-layouts/nl.json
index 61bd4dd61..024713be9 100644
--- a/data/osk-layouts/nl.json
+++ b/data/osk-layouts/nl.json
@@ -91,6 +91,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "á",
@@ -339,6 +340,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "Á",
@@ -574,6 +576,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -822,6 +825,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/no.json b/data/osk-layouts/no.json
index 234b97238..f27ac2abb 100644
--- a/data/osk-layouts/no.json
+++ b/data/osk-layouts/no.json
@@ -594,6 +594,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -842,6 +843,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/ph.json b/data/osk-layouts/ph.json
index 0dbe4f23b..76dedd24c 100644
--- a/data/osk-layouts/ph.json
+++ b/data/osk-layouts/ph.json
@@ -63,6 +63,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a"
             ]
@@ -273,6 +274,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A"
             ]
@@ -498,6 +500,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -746,6 +749,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/pl.json b/data/osk-layouts/pl.json
index dbcd9d6fe..9b95b8e80 100644
--- a/data/osk-layouts/pl.json
+++ b/data/osk-layouts/pl.json
@@ -78,6 +78,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "ą",
@@ -324,6 +325,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "Ą",
@@ -570,6 +572,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -818,6 +821,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/pt.json b/data/osk-layouts/pt.json
index 11c8c6d65..08a406f92 100644
--- a/data/osk-layouts/pt.json
+++ b/data/osk-layouts/pt.json
@@ -90,6 +90,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "á",
@@ -338,6 +339,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "Á",
@@ -574,6 +576,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -822,6 +825,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/ro.json b/data/osk-layouts/ro.json
index 8d14924bc..5c9f7f5ca 100644
--- a/data/osk-layouts/ro.json
+++ b/data/osk-layouts/ro.json
@@ -70,6 +70,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "â",
@@ -300,6 +301,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "Â",
@@ -538,6 +540,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -786,6 +789,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/rs.json b/data/osk-layouts/rs.json
index f0cdb285b..fbd9f3483 100644
--- a/data/osk-layouts/rs.json
+++ b/data/osk-layouts/rs.json
@@ -548,6 +548,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -796,6 +797,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
@@ -962,4 +964,4 @@
   ],
   "locale": "sr",
   "name": "Serbian"
-}
\ No newline at end of file
+}
diff --git a/data/osk-layouts/ru.json b/data/osk-layouts/ru.json
index 154c22eb9..338f6cb9c 100644
--- a/data/osk-layouts/ru.json
+++ b/data/osk-layouts/ru.json
@@ -548,6 +548,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -796,6 +797,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
@@ -962,4 +964,4 @@
   ],
   "locale": "ru",
   "name": "Russian"
-}
\ No newline at end of file
+}
diff --git a/data/osk-layouts/se.json b/data/osk-layouts/se.json
index 0a4bb039c..db2b3db2f 100644
--- a/data/osk-layouts/se.json
+++ b/data/osk-layouts/se.json
@@ -628,6 +628,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -876,6 +877,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/si.json b/data/osk-layouts/si.json
index 7325c4039..bcea9ae42 100644
--- a/data/osk-layouts/si.json
+++ b/data/osk-layouts/si.json
@@ -63,6 +63,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a"
             ]
@@ -278,6 +279,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A"
             ]
@@ -508,6 +510,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -756,6 +759,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/sk.json b/data/osk-layouts/sk.json
index 3e3b696b6..8cc8e9391 100644
--- a/data/osk-layouts/sk.json
+++ b/data/osk-layouts/sk.json
@@ -101,6 +101,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "á",
@@ -381,6 +382,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "Á",
@@ -638,6 +640,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -886,6 +889,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/th.json b/data/osk-layouts/th.json
index 131e5eb48..d52028632 100644
--- a/data/osk-layouts/th.json
+++ b/data/osk-layouts/th.json
@@ -150,6 +150,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "ฟ"
             ]
@@ -464,6 +465,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "ฤ"
             ]
@@ -716,6 +718,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -965,6 +968,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
@@ -1132,4 +1136,4 @@
   ],
   "locale": "th",
   "name": "Thai"
-}
\ No newline at end of file
+}
diff --git a/data/osk-layouts/tr.json b/data/osk-layouts/tr.json
index de2b8f3c0..aa09cae5b 100644
--- a/data/osk-layouts/tr.json
+++ b/data/osk-layouts/tr.json
@@ -83,6 +83,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "â"
@@ -322,6 +323,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "Â"
@@ -556,6 +558,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -804,6 +807,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/ua.json b/data/osk-layouts/ua.json
index b32b6b502..aa3ac741f 100644
--- a/data/osk-layouts/ua.json
+++ b/data/osk-layouts/ua.json
@@ -550,6 +550,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -799,6 +800,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
@@ -966,4 +968,4 @@
   ],
   "locale": "uk",
   "name": "Ukrainian"
-}
\ No newline at end of file
+}
diff --git a/data/osk-layouts/uk.json b/data/osk-layouts/uk.json
index 6b00c34d2..69c7313e7 100644
--- a/data/osk-layouts/uk.json
+++ b/data/osk-layouts/uk.json
@@ -86,6 +86,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "à",
@@ -330,6 +331,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "À",
@@ -566,6 +568,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -814,6 +817,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "€"
             ]
diff --git a/data/osk-layouts/us-extended.json b/data/osk-layouts/us-extended.json
index 2c58b995d..0d5bc96de 100644
--- a/data/osk-layouts/us-extended.json
+++ b/data/osk-layouts/us-extended.json
@@ -626,6 +626,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -874,6 +875,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/us.json b/data/osk-layouts/us.json
index b34b16bc0..922ef9295 100644
--- a/data/osk-layouts/us.json
+++ b/data/osk-layouts/us.json
@@ -86,6 +86,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "à",
@@ -330,6 +331,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "À",
@@ -566,6 +568,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -814,6 +817,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/vn.json b/data/osk-layouts/vn.json
index 17c7f0ed3..01af2698e 100644
--- a/data/osk-layouts/vn.json
+++ b/data/osk-layouts/vn.json
@@ -112,6 +112,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "à",
@@ -389,6 +390,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "À",
@@ -632,6 +634,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -881,6 +884,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/data/osk-layouts/za.json b/data/osk-layouts/za.json
index 0e8dd96b3..fae0980ec 100644
--- a/data/osk-layouts/za.json
+++ b/data/osk-layouts/za.json
@@ -94,6 +94,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "a",
               "á",
@@ -345,6 +346,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "A",
               "Á",
@@ -580,6 +582,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "@"
             ]
@@ -828,6 +831,7 @@
         ],
         [
           {
+            "leftOffset": 0.5,
             "strings": [
               "£"
             ]
diff --git a/js/ui/keyboard.js b/js/ui/keyboard.js
index fb83db7e9..bf6317840 100644
--- a/js/ui/keyboard.js
+++ b/js/ui/keyboard.js
@@ -113,10 +113,10 @@ class KeyContainer extends St.Widget {
         this._rows.push(row);
     }
 
-    appendKey(key, width = 1, height = 1) {
-        let keyInfo = {
+    appendKey(key, width = 1, height = 1, leftOffset = 0) {
+        const keyInfo = {
             key,
-            left: this._currentCol,
+            left: this._currentCol + leftOffset,
             top: this._currentRow,
             width,
             height,
@@ -126,37 +126,19 @@ class KeyContainer extends St.Widget {
         row.keys.push(keyInfo);
         row.width += width;
 
-        this._currentCol += width;
+        this._currentCol += leftOffset + width;
         this._maxCols = Math.max(this._currentCol, this._maxCols);
     }
 
     layoutButtons() {
-        let nCol = 0, nRow = 0;
-
-        for (let i = 0; i < this._rows.length; i++) {
-            let row = this._rows[i];
-
-            /* When starting a new row, see if we need some padding */
-            if (nCol === 0) {
-                let diff = this._maxCols - row.width;
-                if (diff >= 1)
-                    nCol = diff * KEY_SIZE / 2;
-                else
-                    nCol = diff * KEY_SIZE;
-            }
-
-            for (let j = 0; j < row.keys.length; j++) {
-                let keyInfo = row.keys[j];
-                let width = keyInfo.width * KEY_SIZE;
-                let height = keyInfo.height * KEY_SIZE;
-
-                this._gridLayout.attach(keyInfo.key, nCol, nRow, width, height);
-                nCol += width;
-            }
-
-            nRow += KEY_SIZE;
-            nCol = 0;
-        }
+        this._rows.forEach(row => {
+            row.keys.forEach(keyInfo => {
+                const {left, top, width, height} = keyInfo;
+                this._gridLayout.attach(keyInfo.key,
+                                        left * KEY_SIZE, top * KEY_SIZE,
+                                        width * KEY_SIZE, height * KEY_SIZE);
+            });
+        });
     }
 
     getRatio() {
@@ -1582,7 +1564,7 @@ export const Keyboard = GObject.registerClass({
             if (key.action || key.keyval)
                 button.keyButton.add_style_class_name('default-key');
 
-            layout.appendKey(button, key.width);
+            layout.appendKey(button, key.width, 1, key.leftOffset);
         }
     }