I just mapped my mouse key

first
sezanzeb 4 years ago
parent 5a499f6467
commit 7a86dfa179

@ -34,9 +34,9 @@ sudo python3 setup.py install && sudo python3 tests/test.py
- [x] show a dropdown to select an arbitrary device from `xinput list`
- [x] creating presets per device
- [ ] renaming presets
- [x] renaming presets
- [x] show a list that can be extended with a `[+]` button
- [ ] The list shows `[keycode, current key for that keycode -> target]`
- [ ] generate a file for /usr/share/X11/xkb/symbols/ for each preset, (symlink to home .config/?)
- [x] generate a file for /usr/share/X11/xkb/symbols/ for each preset, (symlink to home .config/?)
- [x] load that file with `setxkbmap`
- [ ] automatically load the preset (on startup?, udev on mouse connect?)

@ -54,7 +54,6 @@ class SingleKeyMapping:
def put_together(self):
"""Create all GTK widgets."""
delete_button = Gtk.Button()
destroy_icon = Gtk.Image.new_from_icon_name(
'window-close', Gtk.IconSize.BUTTON
@ -145,9 +144,24 @@ class Window:
# and select the newest one (on the top)
preset_selection.set_active(0)
def clear_mapping_table(self):
"""Remove all rows from the mappings table."""
key_list = self.get('key_list')
for i in range(self.rows):
key_list.remove_row(i + 1)
self.rows = 0
def update_mappings(self):
"""Construct the mapping from the inputs without saving or applying."""
self.mappings = [(10, 'c')]
key_list = self.get('key_list')
mappings = []
for i in range(self.rows):
code = key_list.get_child_at(1, i + 1).get_text()
character = key_list.get_child_at(2, i + 1).get_text()
if code == '' or character == '':
continue
mappings.append((int(code), character))
self.mappings = mappings
def on_save_preset_clicked(self, button):
"""Save changes to a preset to the file system."""
@ -201,22 +215,15 @@ class Window:
self.selected_preset = preset
self.mappings = []
# prepare one empty input to add stuff, and to get the grid to
# the correct column width, otherwise it may jump if the user adds
# the first row.
key_list = self.get('key_list')
for i in range(self.rows):
# don't remove the header
key_list.remove_row(i + 1)
self.rows = 0
# TODO show all mapped keys from config
self.clear_mapping_table()
self.on_add_key_clicked()
def on_add_key_clicked(self, button=None):
"""Add a mapping to the list of mappings."""
# TODO automatically add a line when no line is empty anymore
# TODO automatically add a line when no line is empty anymore,
# making the add button obsolete
single_key_mapping = SingleKeyMapping(self.on_row_removed)
key_list = self.get('key_list')
key_list.insert_row(1)

@ -40,7 +40,7 @@ from keymapper.paths import get_home_path, get_usr_path, KEYCODES_PATH, \
from keymapper.logger import logger
from keymapper.data import get_data_path
from keymapper.presets import get_presets
from keymapper.linux import get_devices
from keymapper.linux import get_devices, can_grab
def get_keycode(device, letter):
@ -63,7 +63,7 @@ def create_preset(device, name=None):
i += 1
name = f'{name} {i}'
create_setxkbmap_config(device, name, [])
os.mknod(get_home_path(device, name))
return name
@ -76,7 +76,18 @@ def create_setxkbmap_config(device, preset, mappings):
/usr/share/X11/xkb/symbols/key-mapper/<device>/<preset> to point to it.
The file in home doesn't have underscore to be more beautiful on the
frontend, while the symlink doesn't contain any whitespaces.
Parameters
----------
device : string
preset : string
mappings : list
List of (keycode, character) tuples
"""
if len(mappings) == 0:
logger.debug('Got empty mappings')
return None
create_identity_mapping()
home_device_path = get_home_path(device)
@ -98,27 +109,34 @@ def create_setxkbmap_config(device, preset, mappings):
logger.info('Writing key mappings')
with open(home_preset_path, 'w') as f:
f.write(generate_symbols_file_content(device, preset, mappings))
contents = generate_symbols_file_content(device, preset, mappings)
if contents is not None:
f.write(contents)
def apply_preset(device, preset):
"""Apply a preset to the device."""
group = get_devices()[device]
# apply it to every device that hangs on the same usb port, because I
# have no idea how to figure out which one of those 3 devices that are
# all named after my mouse to use.
device_underscored = device.replace(' ', '_')
preset_underscored = preset.replace(' ', '_')
group = get_devices()[device]
for xinput_name, xinput_id in get_xinput_id_mapping():
if xinput_name not in group['devices']:
# only all virtual devices of the same hardware device
continue
layout_name = (
'key-mapper'
f'/{device_underscored}'
f'/{preset_underscored}'
)
"""# get the path in /dev for that
path = [
path for name, path
in zip(group['devices'], group['paths'])
if name == xinput_name
][0]
if not can_grab(path):
logger.error('Something else is')"""
symbols = '/usr/share/X11/xkb/symbols/'
layout_name = get_usr_path(device, preset)[len(symbols):]
cmd = [
'setxkbmap',
'-layout', layout_name,
@ -188,6 +206,9 @@ def generate_symbols_file_content(device, preset, mappings):
if f'<{code}>' not in keycodes:
logger.error(f'Unknown keycode <{code}> for "{character}"')
xkb_symbols.append(f'key <{code}> {{ [ {character} ] }};')
if len(xkb_symbols) == 0:
logger.error('Failed to populate xkb_symbols')
return None
template_path = get_data_path('xkb_symbols_template')
with open(template_path, 'r') as template_file:

Loading…
Cancel
Save