From ba929fce23c6714157039e3666056264f64a996f Mon Sep 17 00:00:00 2001 From: sezanzeb Date: Wed, 25 Nov 2020 21:55:04 +0100 Subject: [PATCH] wip --- README.md | 9 +++--- bin/key-mapper-service | 6 ++-- data/key-mapper-service.desktop | 8 +++++ data/key-mapper.glade | 13 +++++--- ...rg.key-mapper.policy => key-mapper.policy} | 2 +- data/key-mapper.service | 12 +++++++ data/style.css | 8 +++++ keymapper/daemon.py | 31 +++++++++---------- keymapper/gtk/row.py | 13 ++++---- keymapper/logger.py | 4 ++- setup.py | 8 +++-- 11 files changed, 75 insertions(+), 39 deletions(-) create mode 100644 data/key-mapper-service.desktop rename data/{org.key-mapper.policy => key-mapper.policy} (95%) create mode 100644 data/key-mapper.service diff --git a/README.md b/README.md index 38f5208d..e6990231 100644 --- a/README.md +++ b/README.md @@ -8,25 +8,26 @@ Tool to change the mapping of your input device buttons. # Running -First, install the package: +Installation: ```bash git clone https://github.com/sezanzeb/key-mapper.git cd key-mapper sudo python3 setup.py install +usermod -a -G input $USER ``` To keep injecting the mapping after closing the window, the daemon needs to -be running: +be running. If it doesn't already after logging in, you can use: ```bash -sudo key-mapper-service -d +sudo key-mapper-service ``` To open the UI to modify the mappings, use: ```bash -sudo key-mapper-gtk -d +sudo key-mapper-gtk ``` You can also start it via your applications menu. diff --git a/bin/key-mapper-service b/bin/key-mapper-service index 920fe671..0daa6e26 100755 --- a/bin/key-mapper-service +++ b/bin/key-mapper-service @@ -33,7 +33,8 @@ from gi.repository import GLib import dbus.mainloop.glib from dbus.mainloop.glib import DBusGMainLoop -from keymapper.logger import logger, update_verbosity, log_info +from keymapper.logger import logger, update_verbosity, log_info, \ + add_filehandler from keymapper.daemon import Daemon @@ -47,13 +48,14 @@ if __name__ == '__main__': options = parser.parse_args(sys.argv[1:]) update_verbosity(options.debug) + add_filehandler() log_info() if getpass.getuser() != 'root' and 'unittest' not in sys.modules.keys(): logger.warning('Without sudo, your devices may not be visible') session_bus = dbus.SessionBus(mainloop=DBusGMainLoop()) - name = dbus.service.BusName('com.keymapper.Control', session_bus) + name = dbus.service.BusName('keymapper.Control', session_bus) daemon = Daemon(session_bus, '/') atexit.register(daemon.stop) diff --git a/data/key-mapper-service.desktop b/data/key-mapper-service.desktop new file mode 100644 index 00000000..1c67b594 --- /dev/null +++ b/data/key-mapper-service.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Type=Application +Name=Key Mapper Service +Icon=mouse +Exec=key-mapper-service +Terminal=false +Categories=Settings; +Comment=The Key Mapper service to keep mappings alive after closing the UI diff --git a/data/key-mapper.glade b/data/key-mapper.glade index f65fe2dc..18aebdd9 100644 --- a/data/key-mapper.glade +++ b/data/key-mapper.glade @@ -601,6 +601,7 @@ + 250 True False vertical @@ -608,16 +609,15 @@ True False - True + 50 True False Click on a cell below and hit a key on your device. If you have your preset active, the reported keycodes may be wrong. 5 5 Key - 10 False @@ -637,16 +637,16 @@ 5 5 Mapping - 10 - False + True True 1 + 50 True False @@ -656,6 +656,9 @@ 2 + False @@ -700,7 +703,7 @@ - False + True True 2 diff --git a/data/org.key-mapper.policy b/data/key-mapper.policy similarity index 95% rename from data/org.key-mapper.policy rename to data/key-mapper.policy index 80bea32f..ef8548b3 100644 --- a/data/org.key-mapper.policy +++ b/data/key-mapper.policy @@ -5,7 +5,7 @@ > mouse - + Run Key Mapper as root Authentication is required to discover devices. diff --git a/data/key-mapper.service b/data/key-mapper.service new file mode 100644 index 00000000..82a8ca68 --- /dev/null +++ b/data/key-mapper.service @@ -0,0 +1,12 @@ +# https://wiki.archlinux.org/index.php/Systemd + +[Unit] +Description=Service to inject keycodes without the GUI application + +[Service] +Type=dbus +BusName=keymapper.Control +ExecStart=/usr/bin/key-mapper-service -d + +[Install] +WantedBy=default.target diff --git a/data/style.css b/data/style.css index 2f1d893c..87a8d977 100644 --- a/data/style.css +++ b/data/style.css @@ -1,3 +1,11 @@ +row { + padding: 0; +} + +.table-header, .row-box { + padding: 2px; +} + .changed { background: @selected_bg_color; } diff --git a/keymapper/daemon.py b/keymapper/daemon.py index c743d8ac..5701fad4 100644 --- a/keymapper/daemon.py +++ b/keymapper/daemon.py @@ -28,10 +28,8 @@ from dbus import service import dbus.mainloop.glib from keymapper.logger import logger -from keymapper.config import config from keymapper.injector import KeycodeInjector from keymapper.mapping import Mapping -from keymapper.paths import get_config_path # TODO service file in data for a root daemon @@ -59,13 +57,13 @@ def get_dbus_interface(): 'The daemon "key-mapper-service" is not running, mapping keys ' 'only works as long as the window is open.' ) - return Daemon(autoload=False) + return Daemon() try: logger.debug('Found the daemon process') bus = dbus.SessionBus() - remote_object = bus.get_object('com.keymapper.Control', '/') - interface = dbus.Interface(remote_object, 'com.keymapper.Interface') + remote_object = bus.get_object('keymapper.Control', '/') + interface = dbus.Interface(remote_object, 'keymapper.Interface') logger.debug('Connected to dbus') except Exception as error: logger.error( @@ -74,7 +72,7 @@ def get_dbus_interface(): 'key-mapper processes not running as root?' ) logger.error(error) - return Daemon(autoload=False) + return Daemon() return interface @@ -83,20 +81,19 @@ class Daemon(service.Object): """Starts injecting keycodes based on the configuration. Can be talked to either over dbus or by instantiating it. + + The Daemon may not have any knowledge about the logged in user, so it + can't read any config files. It has to be told what to do and will + continue to do so afterwards, but it can't decide to start injecting + on its own. """ - def __init__(self, *args, autoload=True, **kwargs): + def __init__(self, *args, **kwargs): """Constructs the daemon. You still need to run the GLib mainloop.""" self.injectors = {} - if autoload: - for device, preset in config.iterate_autoload_presets(): - mapping = Mapping() - mapping.load(get_config_path(device, preset)) - self.injectors[device] = KeycodeInjector(device, mapping) - super().__init__(*args, **kwargs) @dbus.service.method( - 'com.keymapper.Interface', + 'keymapper.Interface', in_signature='s' ) def stop_injecting(self, device): @@ -113,7 +110,7 @@ class Daemon(service.Object): # TODO if ss is the correct signature for multiple parameters, add an # example to https://gitlab.freedesktop.org/dbus/dbus-python/-/blob/master/doc/tutorial.txt # noqa pylint: disable=line-too-long @dbus.service.method( - 'com.keymapper.Interface', + 'keymapper.Interface', in_signature='ss' ) def start_injecting(self, device, path): @@ -143,9 +140,9 @@ class Daemon(service.Object): return True @dbus.service.method( - 'com.keymapper.Interface' + 'keymapper.Interface' ) def stop(self): - """Properly stop the daemon.""" + """Stop all mapping injections.""" for injector in self.injectors.values(): injector.stop_injecting() diff --git a/keymapper/gtk/row.py b/keymapper/gtk/row.py index 27829571..5aa382d6 100644 --- a/keymapper/gtk/row.py +++ b/keymapper/gtk/row.py @@ -132,10 +132,10 @@ class Row(Gtk.ListBoxRow): 'button-press-event', self.on_delete_button_clicked ) - delete_button.set_margin_start(5) - delete_button.set_margin_end(5) + delete_button.set_size_request(50, -1) keycode_input = Gtk.ToggleButton() + keycode_input.set_size_request(50, -1) if keycode is not None: keycode_input.set_label(str(keycode)) @@ -159,12 +159,13 @@ class Row(Gtk.ListBoxRow): ) box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) - box.set_homogeneous(True) - box.set_spacing(2) - box.pack_start(keycode_input, expand=True, fill=True, padding=0) + box.set_homogeneous(False) + box.set_spacing(0) + box.pack_start(keycode_input, expand=False, fill=True, padding=0) box.pack_start(character_input, expand=True, fill=True, padding=0) - box.pack_start(delete_button, expand=True, fill=False, padding=0) + box.pack_start(delete_button, expand=False, fill=True, padding=0) box.show_all() + box.get_style_context().add_class('row-box') self.add(box) self.show_all() diff --git a/keymapper/logger.py b/keymapper/logger.py index 0b437ab8..32fd4afe 100644 --- a/keymapper/logger.py +++ b/keymapper/logger.py @@ -105,7 +105,6 @@ def update_verbosity(debug): def add_filehandler(): """Clear the existing logfile and start logging to it.""" - # jack also logs to ~/.log log_path = os.path.expanduser('~/.log/key-mapper') log_file = os.path.join(log_path, 'log') @@ -118,4 +117,7 @@ def add_filehandler(): file_handler = logging.FileHandler(log_file) file_handler.setFormatter(Formatter()) + + logger.info('Logging to "%s"', log_file) + logger.addHandler(file_handler) diff --git a/setup.py b/setup.py index 86c385b5..95be438f 100644 --- a/setup.py +++ b/setup.py @@ -34,7 +34,7 @@ class Install(DistUtilsExtra.auto.install_auto): executable = os.path.join(self.install_data, 'bin/key-mapper-gtk') assert os.path.exists(executable) - policy_path = '/usr/share/polkit-1/actions/org.key-mapper.policy' + policy_path = '/usr/share/polkit-1/actions/key-mapper.policy' with open(policy_path, 'r') as file: contents = file.read() @@ -45,7 +45,7 @@ class Install(DistUtilsExtra.auto.install_auto): with open(policy_path, 'w') as file: print( f'Inserting the correct path "{executable}" into ' - 'org.key-mapper.policy' + 'keymapper.policy' ) file.write(contents.format( executable=executable @@ -59,7 +59,9 @@ DistUtilsExtra.auto.setup( license='GPL-3.0', data_files=[ ('share/applications/', ['data/key-mapper.desktop']), - ('/usr/share/polkit-1/actions/', ['data/org.key-mapper.policy']), + ('/usr/share/polkit-1/actions/', ['data/key-mapper.policy']), + ('/usr/lib/systemd/system', ['data/key-mapper.service']), + ('/etc/xdg/autostart/', ['data/key-mapper-autoload']), ], cmdclass={ 'install': Install