diff --git a/bin/key-mapper-gtk b/bin/key-mapper-gtk index 930df28e..d8e5fda0 100755 --- a/bin/key-mapper-gtk +++ b/bin/key-mapper-gtk @@ -28,7 +28,7 @@ from argparse import ArgumentParser import gi gi.require_version('Gtk', '3.0') gi.require_version('GLib', '2.0') -from gi.repository import Gtk +from gi.repository import Gtk, Gdk from keymapper.data import get_data_path from keymapper.X import create_setxkbmap_config, apply_preset, create_preset @@ -41,6 +41,9 @@ from keymapper.linux import get_devices window = None +# TODO check for sudo rights + + class SingleKeyMapping: """A single, configurable key mapping.""" def __init__(self, delete_callback): @@ -54,24 +57,27 @@ class SingleKeyMapping: def put_together(self): """Create all GTK widgets.""" - delete_button = Gtk.Button() - destroy_icon = Gtk.Image.new_from_icon_name( + delete_button = Gtk.EventBox() + delete_button.add(Gtk.Image.new_from_icon_name( 'window-close', Gtk.IconSize.BUTTON - ) - delete_button.set_image(destroy_icon) - delete_button.connect('clicked', self.on_delete_button_clicked) + )) + delete_button.connect('button-press-event', self.on_delete_button_clicked) + delete_button.set_margin_start(5) + delete_button.set_margin_end(5) key_code = Gtk.Entry() key_code.set_alignment(0.5) key_code.set_width_chars(4) + key_code.set_has_frame(False) original_key = Gtk.Entry() original_key.set_alignment(0.5) original_key.set_width_chars(4) + original_key.set_has_frame(False) - self.widgets = (delete_button, key_code, original_key) + self.widgets = (key_code, original_key, delete_button) - def on_delete_button_clicked(self, button): + def on_delete_button_clicked(self, *args): """Destroy the row and remove it from the config.""" for widget in self.widgets: widget.destroy() @@ -92,7 +98,7 @@ class Window: builder.connect_signals(self) self.builder = builder - window = builder.get_object('window') + window = self.get('window') window.show() self.window = window @@ -100,6 +106,14 @@ class Window: self.select_newest_preset() + css_provider = Gtk.CssProvider() + css_provider.load_from_path(get_data_path('style.css')) + Gtk.StyleContext.add_provider_for_screen( + Gdk.Screen.get_default(), + css_provider, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION + ) + def get(self, name): """Get a widget from the window""" return self.builder.get_object(name) @@ -216,23 +230,18 @@ class Window: self.mappings = [] # 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, - # making the add button obsolete single_key_mapping = SingleKeyMapping(self.on_row_removed) key_list = self.get('key_list') - key_list.insert_row(1) + row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) + row.set_homogeneous(True) widgets = single_key_mapping.get_widgets() - key_list.attach(widgets[0], 0, 1, 1, 1) - key_list.attach(widgets[1], 1, 1, 1, 1) - key_list.attach(widgets[2], 2, 1, 1, 1) + row.pack_start(widgets[0], expand=True, fill=True, padding=0) + row.pack_start(widgets[1], expand=True, fill=True, padding=0) + row.pack_start(widgets[2], expand=True, fill=True, padding=0) + key_list.insert(row, -1) key_list.show_all() - self.rows += 1 + + self.clear_mapping_table() def on_row_removed(self, mapping): """Stuff to do when a row was removed diff --git a/data/key-mapper.glade b/data/key-mapper.glade index 90f8abc8..879489cd 100644 --- a/data/key-mapper.glade +++ b/data/key-mapper.glade @@ -8,6 +8,48 @@ asdf 0.5 + + True + True + + + True + False + 2 + + + True + False + 10 + 5 + True + Key + 10 + + + 0 + 0 + + + + + True + False + 10 + 5 + True + Mapping + 10 + + + 1 + 0 + + + + 450 False @@ -133,18 +175,6 @@ 2 - - - True - False - 0 - - - True - True - 3 - - gtk-delete @@ -272,38 +302,37 @@ - 200 True False vertical - + True False - 10 + True - 50 True False - Mapping - 0 + 5 + 5 + Key + 10 - True + False True 0 - - gtk-add - 80 + True - True - True - True - + False + 5 + 5 + Mapping + 10 False @@ -311,6 +340,17 @@ 1 + + + True + False + + + False + True + 2 + + False @@ -319,48 +359,28 @@ - + True False - 10 - 10 - 10 - 2 - 2 - - - True - False - True - Mapping - - - 2 - 0 - - - - - True - False - True - Key - - - 1 - 0 - - - - - - True + False True 1 + + + True + False + none + + + True + True + 2 + + False diff --git a/data/screenshot.png b/data/screenshot.png index 25786349..3d938488 100644 Binary files a/data/screenshot.png and b/data/screenshot.png differ diff --git a/data/style.css b/data/style.css new file mode 100644 index 00000000..8ebd8d2f --- /dev/null +++ b/data/style.css @@ -0,0 +1,5 @@ +list entry { + background-color: transparent; +} + +/* @theme_bg_color, @theme_fg_color */ \ No newline at end of file diff --git a/keymapper/X.py b/keymapper/X.py index 4c1fd297..219c60ee 100644 --- a/keymapper/X.py +++ b/keymapper/X.py @@ -220,6 +220,8 @@ def generate_symbols_file_content(device, preset, mappings): for code, character in mappings: if f'<{code}>' not in keycodes: logger.error(f'Unknown keycode <{code}> for "{character}"') + # continue, otherwise X would crash when loading + continue xkb_symbols.append(f'key <{code}> {{ [ {character} ] }};') if len(xkb_symbols) == 0: logger.error('Failed to populate xkb_symbols')