diff --git a/docs/installation.md b/docs/installation.md index ca5f7c55..a359864b 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -24,6 +24,7 @@ Solaar requires Python 3.7+ and requires several packages to be installed. If you are running the system version of Python you should have the `python3-pyudev`, `python3-psutil`, `python3-xlib`, `python3-evdev`, and `python3-yaml` or `python3-pyyaml` packages installed. + To run the GUI Solaar also requires Gtk3 and its GObject introspection bindings. If you are running the system version of Python the Debian/Ubuntu packages you should have @@ -31,6 +32,10 @@ the Debian/Ubuntu packages you should have in Fedora you need `gtk3` and `python3-gobject`. You may have to install `gcc` and the Python development package (`python3-dev` or `python3-devel`, depending on your distribution). +Although the Solaar CLI does not require Gtk3, +`solaar config` does use Gtk3 capabilities to determine whether the Solaar GUI is running +and thus should tell the Solaar GUI to update its information about settings +so it is a good idea to have Gtk3 available even for the Solaar CLI. If the `hid_parser` Python package is available, Solaar parses HID report descriptors and can control more HID++ devices that do not use a receiver. diff --git a/lib/solaar/cli/config.py b/lib/solaar/cli/config.py index baaf3fca..3230a1b2 100644 --- a/lib/solaar/cli/config.py +++ b/lib/solaar/cli/config.py @@ -23,10 +23,6 @@ from logitech_receiver import settings_templates as _settings_templates from logitech_receiver.common import NamedInts as _NamedInts from solaar import configuration as _configuration -import gi # isort:skip -gi.require_version('Gtk', '3.0') # NOQA: E402 -from gi.repository import Gio, Gtk # NOQA: E402 # isort:skip - def _print_setting(s, verbose=True): print('#', s.label) @@ -188,11 +184,17 @@ def run(receivers, args, find_receiver, find_device): return remote = False - if Gtk.init_check()[0]: # can Gtk be initialized? - APP_ID = 'io.github.pwr_solaar.solaar' - application = Gtk.Application.new(APP_ID, Gio.ApplicationFlags.HANDLES_COMMAND_LINE) - application.register() - remote = application.get_is_remote() + try: + import gi + gi.require_version('Gtk', '3.0') + from gi.repository import Gio, Gtk + if Gtk.init_check()[0]: # can Gtk be initialized? + APP_ID = 'io.github.pwr_solaar.solaar' + application = Gtk.Application.new(APP_ID, Gio.ApplicationFlags.HANDLES_COMMAND_LINE) + application.register() + remote = application.get_is_remote() + except Exception: + pass # don't save configuration here because we might want the Solaar GUI to make the change result, message, value = set(dev, setting, args, False) @@ -209,7 +211,6 @@ def run(receivers, args, find_receiver, find_device): else: if dev.persister and setting.persist: dev.persister[setting.name] = setting._value - _configuration.save(defer=False) def set(dev, setting, args, save): diff --git a/lib/solaar/configuration.py b/lib/solaar/configuration.py index 5a303793..47daf73a 100644 --- a/lib/solaar/configuration.py +++ b/lib/solaar/configuration.py @@ -28,7 +28,6 @@ from threading import Timer as _Timer import yaml as _yaml -from gi.repository import GLib from logitech_receiver.common import NamedInt as _NamedInt from solaar import __version__ @@ -73,6 +72,7 @@ def _load(): save_timer = None save_lock = _Lock() +defer_saves = False # don't allow configuration saves to be deferred def save(defer=False): @@ -86,11 +86,12 @@ def save(defer=False): except Exception: _log.error('failed to create %s', dirname) return - if not defer: + if not defer or not defer_saves: do_save() else: with save_lock: if not save_timer: + from gi.repository import GLib save_timer = _Timer(5.0, lambda: GLib.idle_add(do_save)) save_timer.start() diff --git a/lib/solaar/gtk.py b/lib/solaar/gtk.py index ed26e93a..24acd6ec 100755 --- a/lib/solaar/gtk.py +++ b/lib/solaar/gtk.py @@ -170,6 +170,9 @@ def main(): else: _upower.watch(lambda: listener.ping_all(True)) + import solaar.configuration as _configuration + _configuration.defer_saves = True # allow configuration saves to be deferred + # main UI event loop ui.run_loop(listener.start_all, listener.stop_all, args.window != 'only', args.window != 'hide') except Exception: