Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 84 additions & 16 deletions data/input-remapper.glade
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
<object class="GtkWindow" id="window">
<property name="width-request">1000</property>
<property name="can-focus">False</property>
<property name="default-height">450</property>
<property name="default-height">636</property>
<property name="icon">input-remapper.svg</property>
<signal name="delete-event" handler="on_gtk_close" swapped="no"/>
<child>
Expand All @@ -116,31 +116,99 @@
<property name="can-focus">False</property>
<property name="transition-type">crossfade</property>
<child>
<object class="GtkScrolledWindow">
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkViewport">
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="shadow-type">none</property>
<property name="halign">center</property>
<property name="margin-left">18</property>
<property name="margin-right">18</property>
<property name="margin-start">18</property>
<property name="margin-end">18</property>
<property name="margin-top">27</property>
<property name="margin-bottom">27</property>
<property name="spacing">12</property>
<child>
<object class="GtkSwitch" id="group_all">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="active">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFlowBox" id="device_selection">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="valign">start</property>
<property name="margin-start">18</property>
<property name="margin-end">18</property>
<property name="margin-top">18</property>
<property name="margin-bottom">18</property>
<property name="homogeneous">True</property>
<property name="column-spacing">18</property>
<property name="row-spacing">18</property>
<property name="max-children-per-line">99</property>
<property name="selection-mode">none</property>
<property name="tooltip-text" translatable="yes">Activate this to apply a different preset to each individual device.</property>
<property name="opacity">0.5</property>
<property name="label" translatable="yes">Map devices individually</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<child>
<object class="GtkViewport">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="shadow-type">none</property>
<child>
<object class="GtkFlowBox" id="device_selection">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="valign">start</property>
<property name="margin-start">18</property>
<property name="margin-end">18</property>
<property name="margin-top">18</property>
<property name="margin-bottom">18</property>
<property name="homogeneous">True</property>
<property name="column-spacing">18</property>
<property name="row-spacing">18</property>
<property name="max-children-per-line">99</property>
<property name="selection-mode">none</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
Expand Down
18 changes: 9 additions & 9 deletions inputremapper/bin/input_remapper_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@

import gi

from inputremapper.groups import Groups

gi.require_version("GLib", "2.0")
from gi.repository import GLib

Expand Down Expand Up @@ -70,7 +72,9 @@ def __init__(
self,
global_config: GlobalConfig,
migrations: Migrations,
groups: Groups,
):
self.groups = groups
self.global_config = global_config
self.migrations = migrations

Expand All @@ -79,9 +83,11 @@ def main(options: Options) -> None:
global_config = GlobalConfig()
global_uinputs = GlobalUInputs(FrontendUInput)
migrations = Migrations(global_uinputs)
groups = Groups(global_config)
input_remapper_control = InputRemapperControlBin(
global_config,
migrations,
groups,
)

if options.debug:
Expand Down Expand Up @@ -137,9 +143,8 @@ def main(options: Options) -> None:

def list_devices(self):
logger.setLevel(logging.ERROR)
from inputremapper.groups import groups

for group in groups:
for group in self.groups:
print(group.key)

def list_key_names(self):
Expand Down Expand Up @@ -239,19 +244,14 @@ def _start(self, device: str, preset: str) -> None:
self.daemon.start_injecting(group.key, preset)

def _require_group(self, device: str):
# import stuff late to make sure the correct log level is applied
# before anything is logged
# TODO since imports shouldn't run any code, this is fixed by moving towards DI
from inputremapper.groups import groups

if device is None:
logger.error("--device missing")
sys.exit(3)

if device.startswith("/dev"):
group = groups.find(path=device)
group = self.groups.find(path=device)
else:
group = groups.find(key=device)
group = self.groups.find(key=device)

if group is None:
logger.error(
Expand Down
8 changes: 5 additions & 3 deletions inputremapper/bin/input_remapper_gtk.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
from inputremapper.gui.user_interface import UserInterface
from inputremapper.gui.controller import Controller
from inputremapper.injection.global_uinputs import GlobalUInputs, FrontendUInput
from inputremapper.groups import _Groups
from inputremapper.groups import Groups
from inputremapper.gui.reader_client import ReaderClient
from inputremapper.configs.global_config import GlobalConfig
from inputremapper.configs.migrations import Migrations
Expand Down Expand Up @@ -88,10 +88,12 @@ def main() -> Tuple[

global_config = GlobalConfig()

groups = Groups(global_config)

# Create the ReaderClient before we start the reader-service, otherwise the
# privileged service creates and owns those pipes, and then they cannot be accessed
# by the user.
reader_client = ReaderClient(message_broker, _Groups())
reader_client = ReaderClient(message_broker, groups)

if ProcessUtils.count_python_processes("input-remapper-gtk") >= 2:
logger.warning(
Expand All @@ -112,7 +114,7 @@ def main() -> Tuple[
keyboard_layout,
)
controller = Controller(message_broker, data_manager)
user_interface = UserInterface(message_broker, controller)
user_interface = UserInterface(global_config, message_broker, controller)
controller.set_gui(user_interface)

message_broker.signal(MessageType.init)
Expand Down
8 changes: 5 additions & 3 deletions inputremapper/bin/input_remapper_reader_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
from argparse import ArgumentParser

from inputremapper.bin.process_utils import ProcessUtils
from inputremapper.groups import _Groups
from inputremapper.configs.global_config import GlobalConfig
from inputremapper.groups import Groups
from inputremapper.gui.reader_service import ReaderService
from inputremapper.injection.global_uinputs import GlobalUInputs, FrontendUInput
from inputremapper.logging.logger import logger
Expand Down Expand Up @@ -74,7 +75,8 @@ def on_exit():
os.kill(os.getpid(), signal.SIGKILL)

atexit.register(on_exit)
groups = _Groups()
global_config = GlobalConfig()
groups = Groups(global_config)
global_uinputs = GlobalUInputs(FrontendUInput)
reader_service = ReaderService(groups, global_uinputs)
reader_service = ReaderService(global_config, groups, global_uinputs)
asyncio.run(reader_service.run())
9 changes: 8 additions & 1 deletion inputremapper/bin/input_remapper_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from argparse import ArgumentParser

from inputremapper.configs.global_config import GlobalConfig
from inputremapper.groups import Groups
from inputremapper.injection.global_uinputs import GlobalUInputs, UInput
from inputremapper.injection.mapping_handlers.mapping_parser import MappingParser
from inputremapper.logging.logger import logger
Expand Down Expand Up @@ -61,7 +62,13 @@ def main() -> None:
global_config = GlobalConfig()
global_uinputs = GlobalUInputs(UInput)
mapping_parser = MappingParser(global_uinputs)
groups = Groups(global_config)

daemon = Daemon(global_config, global_uinputs, mapping_parser)
daemon = Daemon(
global_config,
global_uinputs,
mapping_parser,
groups,
)
daemon.publish()
daemon.run()
24 changes: 5 additions & 19 deletions inputremapper/configs/base_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,12 @@
from __future__ import annotations

import copy
from typing import Union, List, Optional, Callable, Any
from typing import Union, List, Optional, Callable, Any, Dict

from inputremapper.logging.logger import logger, VERSION

NONE = "none"

INITIAL_CONFIG = {
"version": VERSION,
"autoload": {},
}


class ConfigBase:
"""Base class for config objects.
Expand All @@ -39,17 +34,10 @@ class ConfigBase:
this base.
"""

def __init__(self, fallback: Optional[ConfigBase] = None):
"""Set up the needed members to turn your object into a config.

Parameters
----------
fallback: ConfigBase
a configuration that contains fallback default configs, if your
object doesn't configure a certain key.
"""
def __init__(self, defaults: Optional[Dict] = None):
"""Set up the needed members to turn your object into a config."""
self._config = {}
self.fallback = fallback
self.defaults = defaults

def _resolve(
self,
Expand Down Expand Up @@ -134,11 +122,9 @@ def callback(parent, child, chunk):
return child

resolved = self._resolve(path, callback)
if resolved is None and self.fallback is not None:
resolved = self.fallback._resolve(path, callback)
if resolved is None:
# don't create new empty stuff in INITIAL_CONFIG with _resolve
initial_copy = copy.deepcopy(INITIAL_CONFIG)
initial_copy = copy.deepcopy(self.defaults)
resolved = self._resolve(path, callback, initial_copy)

if resolved is None and log_unknown:
Expand Down
26 changes: 23 additions & 3 deletions inputremapper/configs/global_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
import copy
import json
import os
from typing import Optional
from typing import Optional, Dict

from inputremapper.configs.base_config import ConfigBase, INITIAL_CONFIG
from inputremapper.configs.base_config import ConfigBase
from inputremapper.configs.paths import PathUtils
from inputremapper.logging.logger import logger
from inputremapper.logging.logger import logger, VERSION
from inputremapper.user import UserUtils

MOUSE = "mouse"
Expand All @@ -34,6 +34,17 @@
NONE = "none"


INITIAL_CONFIG = {
"version": VERSION,
"autoload": {},
"groups": {
"map_individually": True,
# Mapping of name to unique group-key
"custom_groups": {},
},
}


class GlobalConfig(ConfigBase):
"""Global default configuration, from which all presets inherit.
It can also contain some extra stuff not relevant for presets, like the
Expand All @@ -44,6 +55,7 @@ class GlobalConfig(ConfigBase):

def __init__(self):
self.path = os.path.join(PathUtils.config_path(), "config.json")
self.defaults = INITIAL_CONFIG
super().__init__()

def get_dir(self) -> str:
Expand All @@ -69,6 +81,14 @@ def set_autoload_preset(self, group_key: str, preset: Optional[str]):

self._save_config()

def set_group_all(self, group_all: bool) -> None:
self.set(["groups", "map_individually"], group_all)
self._save_config()

def set_custom_groups(self, groups: Dict[str, str]) -> None:
self.set(["groups", "custom_groups"], groups)
self._save_config()

def iterate_autoload_presets(self):
"""Get tuples of (device, preset)."""
return self._config.get("autoload", {}).items()
Expand Down
Loading
Loading