summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lulua/keyboard.py71
-rw-r--r--lulua/render.py49
2 files changed, 118 insertions, 2 deletions
diff --git a/lulua/keyboard.py b/lulua/keyboard.py
index c9d3adb..cf96efc 100644
--- a/lulua/keyboard.py
+++ b/lulua/keyboard.py
@@ -225,6 +225,73 @@ _buttonToWinScancode = {
'Fr_ctrl': (0xe0, 0x1D, ),
}
+# see https://eastmanreference.com/complete-list-of-applescript-key-codes
+_buttonToOsxKeycode = {
+ 'Bl1': 50,
+ 'Bl2': 18,
+ 'Bl3': 19,
+ 'Bl4': 20,
+ 'Bl5': 21,
+ 'Bl6': 23,
+ 'Bl7': 22,
+ 'Br6': 26,
+ 'Br5': 28,
+ 'Br4': 25,
+ 'Br3': 29,
+ 'Br2': 27,
+ 'Br1': 24,
+ 'Br_bs': 51,
+ 'Cl_tab': 48,
+ 'Cl1': 12,
+ 'Cl2': 13,
+ 'Cl3': 14,
+ 'Cl4': 15,
+ 'Cl5': 17,
+ 'Cr7': 16,
+ 'Cr6': 32,
+ 'Cr5': 34,
+ 'Cr4': 31,
+ 'Cr3': 35,
+ 'Cr2': 33,
+ 'Cr1': 30,
+ 'CD_ret': 36,
+ 'Dl_caps': 57,
+ 'Dl1': 0,
+ 'Dl2': 1,
+ 'Dl3': 2,
+ 'Dl4': 3,
+ 'Dl5': 5,
+ 'Dr7': 4,
+ 'Dr6': 38,
+ 'Dr5': 40,
+ 'Dr4': 37,
+ 'Dr3': 41,
+ 'Dr2': 39,
+ #'Dr1': 51,
+ 'El_shift': 57,
+ #'El1': 6,
+ 'El2': 6,
+ 'El3': 7,
+ 'El4': 8,
+ 'El5': 9,
+ 'El6': 11,
+ 'Er5': 45,
+ 'Er4': 46,
+ 'Er3': 43,
+ 'Er2': 47,
+ 'Er1': 44,
+ 'Er_shift': 60,
+ 'Fl_ctrl': 59,
+ 'Fl_win': 55,
+ 'Fl_alt': 58,
+ 'Fl_space': 49,
+ 'Fr_space': 49,
+ 'Fr_altgr': 61,
+ 'Fr_win': 55,
+ #'Fr_menu': ,
+ #'Fr_ctrl': 105,
+ }
+
class Button:
__slots__ = ('width', 'isMarked', 'i')
_idToName : Dict[int, Text] = {}
@@ -271,6 +338,10 @@ class Button:
def windowsScancode (self):
return _buttonToWinScancode[self.name]
+ @property
+ def osxKeycode (self):
+ return _buttonToOsxKeycode[self.name]
+
@classmethod
def deserialize (self, data: Dict):
kindMap = {'standard': Button, 'letter': LetterButton, 'multi': MultiRowButton}
diff --git a/lulua/render.py b/lulua/render.py
index b8514f0..08bc9bc 100644
--- a/lulua/render.py
+++ b/lulua/render.py
@@ -23,7 +23,7 @@ from collections import namedtuple, defaultdict
from itertools import chain
from operator import attrgetter
from datetime import datetime
-from xml.etree import ElementTree
+from xml.etree import ElementTree as ET
import svgwrite
import yaml
@@ -410,7 +410,6 @@ def renderAsk (args):
keyboard = defaultKeyboards[args.keyboard]
layout = defaultLayouts[args.layout].specialize (keyboard)
- ET = ElementTree
namespaces = {
'xmlns:android': 'http://schemas.android.com/apk/res/android',
'xmlns:ask': 'http://schemas.android.com/apk/res-auto',
@@ -508,6 +507,50 @@ def renderWinKbd (args):
fd.write (makeDriverSources (scancodeToVk, wcharMap))
+def renderKeylayout (args):
+ """
+ For macOS
+
+ See:
+ https://developer.apple.com/library/archive/technotes/tn2056/_index.html#//apple_ref/doc/uid/DTS10003085
+ """
+
+ logging.info ('MacOS does not support custom modifiers and thus your layout '
+ 'is probably not going to work.')
+
+ keyboard = defaultKeyboards[args.keyboard]
+ layout = defaultLayouts[args.layout].specialize (keyboard)
+ nextId = 0
+
+ docroot = ET.Element('keyboard', group="0", id="14242", name=layout.name, maxout="3")
+
+ # fixed modifiers (XXX)
+ modmapId = nextId
+ modmap = ET.SubElement (docroot, 'modifierMap', id=str (modmapId), defaultIndex='0')
+ nextId += 1
+ for i, keys in enumerate (('', 'anyShift caps?', 'caps', 'anyOption')):
+ keymapSelect = ET.SubElement (modmap, 'keyMapSelect', mapIndex=str (i))
+ modifier = ET.SubElement (keymapSelect, 'modifier', keys=keys)
+
+ # keymaps
+ keymapSetId = nextId
+ keymapSet = ET.SubElement (docroot, 'keyMapSet', id=str (keymapSetId))
+ nextId += 1
+ for i, l in enumerate (layout.layers):
+ keymap = ET.SubElement (keymapSet, 'keyMap', index=str (i))
+ for btn, text in l.layout.items ():
+ ET.SubElement (keymap, 'key', code=str (btn.osxKeycode), output=text)
+
+ layouts = ET.SubElement (docroot, 'layouts')
+ layout = ET.SubElement (layouts, 'layout', first='0', last='0', modifiers=str (modmapId), mapSet=str (keymapSetId))
+
+ decl = b"""<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE keyboard PUBLIC "" "file://localhost/System/Library/DTDs/KeyboardLayout.dtd">
+"""
+ with open (args.output, 'wb') as fd:
+ fd.write (decl)
+ fd.write (ET.tostring (docroot, encoding='utf-8'))
+
def yamlload (s):
try:
with open (s) as fd:
@@ -542,6 +585,8 @@ def render ():
sp.set_defaults (func=renderAsk)
sp = subparsers.add_parser('winkbd')
sp.set_defaults (func=renderWinKbd)
+ sp = subparsers.add_parser('keylayout')
+ sp.set_defaults (func=renderKeylayout)
parser.add_argument('output', metavar='FILE', help='Output file')
logging.basicConfig (level=logging.INFO)