File: input_remapper_gtk.py

package info (click to toggle)
input-remapper 2.1.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 2,856 kB
  • sloc: python: 27,277; sh: 191; xml: 33; makefile: 3
file content (152 lines) | stat: -rwxr-xr-x 4,934 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# -*- coding: utf-8 -*-
# input-remapper - GUI for device specific keyboard mappings
# Copyright (C) 2025 sezanzeb <b8x45ygc9@mozmail.com>
#
# This file is part of input-remapper.
#
# input-remapper 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.
#
# input-remapper 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 input-remapper.  If not, see <https://www.gnu.org/licenses/>.

"""Starts the user interface."""

from __future__ import annotations

import atexit
import sys
from argparse import ArgumentParser
from typing import Tuple

import gi

from inputremapper.bin.process_utils import ProcessUtils

gi.require_version("Gtk", "3.0")
gi.require_version("GLib", "2.0")
gi.require_version("GtkSource", "4")
from gi.repository import Gtk

# https://github.com/Nuitka/Nuitka/issues/607#issuecomment-650217096
Gtk.init()

from inputremapper.gui.gettext import _, LOCALE_DIR
from inputremapper.gui.reader_service import ReaderService
from inputremapper.daemon import DaemonProxy, Daemon
from inputremapper.logging.logger import logger
from inputremapper.gui.messages.message_broker import MessageBroker, MessageType
from inputremapper.configs.keyboard_layout import keyboard_layout
from inputremapper.gui.data_manager import DataManager
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.gui.reader_client import ReaderClient
from inputremapper.configs.global_config import GlobalConfig
from inputremapper.configs.migrations import Migrations


class InputRemapperGtkBin:
    @staticmethod
    def main() -> Tuple[
        UserInterface,
        Controller,
        DataManager,
        MessageBroker,
        DaemonProxy,
        GlobalConfig,
    ]:
        parser = ArgumentParser()
        parser.add_argument(
            "-d",
            "--debug",
            action="store_true",
            dest="debug",
            help=_("Displays additional debug information"),
            default=False,
        )

        options = parser.parse_args(sys.argv[1:])
        logger.update_verbosity(options.debug)
        logger.log_info("input-remapper-gtk")
        logger.debug("Using locale directory: {}".format(LOCALE_DIR))

        global_uinputs = GlobalUInputs(FrontendUInput)

        migrations = Migrations(global_uinputs)
        migrations.migrate()

        message_broker = MessageBroker()

        global_config = GlobalConfig()

        # 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())

        if ProcessUtils.count_python_processes("input-remapper-gtk") >= 2:
            logger.warning(
                "Another input-remapper GUI is already running. "
                "This can cause problems while recording keys"
            )

        InputRemapperGtkBin.start_reader_service()

        daemon = Daemon.connect()

        data_manager = DataManager(
            message_broker,
            global_config,
            reader_client,
            daemon,
            global_uinputs,
            keyboard_layout,
        )
        controller = Controller(message_broker, data_manager)
        user_interface = UserInterface(message_broker, controller)
        controller.set_gui(user_interface)

        message_broker.signal(MessageType.init)

        atexit.register(lambda: InputRemapperGtkBin.stop(daemon, controller))

        Gtk.main()

        # For tests:
        return (
            user_interface,
            controller,
            data_manager,
            message_broker,
            daemon,
            global_config,
        )

    @staticmethod
    def start_reader_service():
        if ProcessUtils.count_python_processes("input-remapper-reader-service") >= 1:
            logger.info("Found an input-remapper-reader-service to already be running")
            return

        try:
            ReaderService.pkexec_reader_service()
        except Exception as e:
            logger.error(e)
            sys.exit(11)

    @staticmethod
    def stop(daemon, controller):
        if isinstance(daemon, Daemon):
            # have fun debugging completely unrelated tests if you remove this
            daemon.stop_all()

        controller.close()