diff --git a/data/key-mapper.glade b/data/key-mapper.glade
index 88a5456f..b1b19b65 100644
--- a/data/key-mapper.glade
+++ b/data/key-mapper.glade
@@ -707,38 +707,4 @@ Control_R
-
diff --git a/keymapper/gtk/loading.py b/keymapper/gtk/loading.py
deleted file mode 100644
index 3e3441ad..00000000
--- a/keymapper/gtk/loading.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/python3
-# -*- coding: utf-8 -*-
-# key-mapper - GUI for device specific keyboard mappings
-# Copyright (C) 2020 sezanzeb
-#
-# This file is part of key-mapper.
-#
-# key-mapper is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# key-mapper is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with key-mapper. If not, see .
-
-
-"""Error dialog."""
-
-
-import gi
-gi.require_version('Gtk', '3.0')
-gi.require_version('GLib', '2.0')
-from gi.repository import Gtk
-
-from keymapper.data import get_data_path
-
-
-class LoadingDialog:
- """Displays 'Loading...' until Key Mapper is loaded."""
- def __init__(self):
- """Open a dialog that says 'Loading...'."""
- gladefile = get_data_path('key-mapper.glade')
- builder = Gtk.Builder()
- builder.add_from_file(gladefile)
- dialog = builder.get_object('loading')
- dialog.show_all()
- self.dialog = dialog
-
- def destroy(self):
- """Destroy this dialog."""
- self.dialog.destroy()
diff --git a/keymapper/gtk/window.py b/keymapper/gtk/window.py
index ba8ecae0..4074a2db 100755
--- a/keymapper/gtk/window.py
+++ b/keymapper/gtk/window.py
@@ -23,6 +23,7 @@
import gi
+import time
gi.require_version('Gtk', '3.0')
gi.require_version('GLib', '2.0')
from gi.repository import Gtk, Gdk, GLib
@@ -101,11 +102,10 @@ class Window:
window = self.get('window')
window.show()
- window.set_sensitive(False)
- self.get('wrapper').set_opacity(0)
- loading = LoadingDialog()
self.window = window
+ # if any of the next steps take a bit to complete, have the window
+ # already visible to make it look more responsive.
gtk_iteration()
self.populate_devices()
@@ -114,10 +114,6 @@ class Window:
self.timeout = GLib.timeout_add(100, self.check_add_row)
- window.set_sensitive(True)
- self.get('wrapper').set_opacity(1)
- loading.destroy()
-
def get(self, name):
"""Get a widget from the window"""
return self.builder.get_object(name)
diff --git a/keymapper/linux.py b/keymapper/linux.py
index da999fde..9dd3648b 100644
--- a/keymapper/linux.py
+++ b/keymapper/linux.py
@@ -23,15 +23,13 @@
import subprocess
+import multiprocessing
import evdev
from keymapper.logger import logger
-_devices = None
-
-
def can_grab(path):
"""Can input events from the device be read?
@@ -100,7 +98,7 @@ class KeycodeReader:
# keycode_reader = KeycodeReader()
-def get_devices():
+def _get_devices(pipe):
"""Group devices and get relevant infos per group.
Returns a list containing mappings of
@@ -112,10 +110,21 @@ def get_devices():
They are grouped by usb port.
"""
- # cache the result, this takes a second to complete
- global _devices
- if _devices is not None:
- return _devices
+ """
+ evdev.list_devices -> string[] dev/input/event# paths
+ device = evdev.InputDevice(path)
+ device.capabilities().keys() ein array mit evdev.ecodes.EV_KEY oder
+ irgendn stuff der nicht interessiert
+
+ device.phys ->
+
+ device.phys usb-0000:03:00.0-4/input2
+ device.phys usb-0000:03:00.0-4/input1
+ device.phys usb-0000:03:00.0-4/input0
+ device.phys usb-0000:03:00.0-3/input1
+ device.phys usb-0000:03:00.0-3/input1
+ device.phys usb-0000:03:00.0-3/input0
+ """
devices = [evdev.InputDevice(path) for path in evdev.list_devices()]
@@ -144,6 +153,18 @@ def get_devices():
'devices': names
}
- _devices = result
- logger.info('Found %s', ', '.join([f'"{name}"' for name in result]))
- return result
+ pipe.send(result)
+
+
+# populate once for the whole app. Since InputDevice destructors take
+# quite some time, do this in a process that can take as much time as it
+# wants after piping the result.
+pipe = multiprocessing.Pipe()
+multiprocessing.Process(target=_get_devices, args=(pipe[1],)).start()
+# block until devices are available
+_devices = pipe[0].recv()
+logger.info('Found %s', ', '.join([f'"{name}"' for name in _devices]))
+
+
+def get_devices():
+ return _devices