1{
2 lib,
3 buildPythonApplication,
4 fetchFromGitHub,
5 pkgconfig,
6 wrapGAppsHook3,
7 gettext,
8 gtk3,
9 glib,
10 dbus,
11 gobject-introspection,
12 xmodmap,
13 pygobject3,
14 setuptools,
15 evdev,
16 pydantic,
17 pydbus,
18 psutil,
19 procps,
20 gtksourceview4,
21 bash,
22 udevCheckHook,
23 nixosTests,
24 # Change the default log level to debug for easier debugging of package issues
25 withDebugLogLevel ? false,
26 # Xmodmap is an optional dependency
27 # If you use Xmodmap to set keyboard mappings (or your DE does)
28 # it is required to correctly map keys
29 withXmodmap ? true,
30 # Some tests are flakey under high CPU load and could cause intermittent
31 # failures when building. Override this to true to run tests anyway
32 # See upstream issue: https://github.com/sezanzeb/input-remapper/issues/306
33 withDoCheck ? false,
34}:
35
36let
37 maybeXmodmap = lib.optional withXmodmap xmodmap;
38in
39(buildPythonApplication rec {
40 pname = "input-remapper";
41 version = "2.1.1";
42 format = "setuptools";
43
44 src = fetchFromGitHub {
45 owner = "sezanzeb";
46 repo = "input-remapper";
47 tag = version;
48 hash = "sha256-GMKcs2UK1yegGT/TBsLGgTBJROQ38M6WwnLbJIuAZwg=";
49 };
50
51 postPatch = ''
52 # fix FHS paths
53 substituteInPlace inputremapper/configs/data.py \
54 --replace-fail "/usr/share" "$out/usr/share"
55 ''
56 + lib.optionalString withDebugLogLevel ''
57 # if debugging
58 substituteInPlace inputremapper/logger.py \
59 --replace-fail "logger.setLevel(logging.INFO)" "logger.setLevel(logging.DEBUG)"
60 '';
61
62 nativeBuildInputs = [
63 wrapGAppsHook3
64 gettext # needed to build translations
65 gtk3
66 glib
67 gobject-introspection
68 pygobject3
69 udevCheckHook
70 ]
71 ++ maybeXmodmap;
72
73 dependencies = [
74 setuptools # needs pkg_resources
75 pygobject3
76 evdev
77 pkgconfig
78 pydantic
79 pydbus
80 gtksourceview4
81 psutil
82 ];
83
84 doCheck = withDoCheck;
85
86 nativeCheckInputs = [ psutil ];
87
88 pythonImportsCheck = [
89 "evdev"
90 "inputremapper"
91 ];
92
93 postInstall = ''
94 substituteInPlace data/99-input-remapper.rules \
95 --replace-fail 'RUN+="/bin/input-remapper-control' "RUN+=\"$out/bin/input-remapper-control"
96 substituteInPlace data/input-remapper.service \
97 --replace-fail "ExecStart=/usr/bin/input-remapper-service" "ExecStart=$out/bin/input-remapper-service"
98 substituteInPlace data/input-remapper-autoload.desktop \
99 --replace-fail "bash" "${lib.getExe bash}"
100
101 install -m644 -D -t $out/share/applications/ data/*.desktop
102 install -m644 -D -t $out/share/polkit-1/actions/ data/input-remapper.policy
103 install -m644 -D data/99-input-remapper.rules $out/etc/udev/rules.d/99-input-remapper.rules
104 install -m644 -D data/input-remapper.service $out/lib/systemd/system/input-remapper.service
105 install -m644 -D data/input-remapper.policy $out/share/polkit-1/actions/input-remapper.policy
106 install -m644 -D data/inputremapper.Control.conf $out/etc/dbus-1/system.d/inputremapper.Control.conf
107 install -m644 -D data/input-remapper.svg $out/share/icons/hicolor/scalable/apps/input-remapper.svg
108 install -m644 -D -t $out/usr/share/input-remapper/ data/*
109
110 # Only install input-remapper prefixed binaries, we don't care about deprecated key-mapper ones
111 install -m755 -D -t $out/bin/ bin/input-remapper*
112 '';
113
114 # Custom test script, can't use plain pytest / pytestCheckHook
115 # We only run tests in the unit folder, integration tests require UI
116 # To allow tests which access the system and session DBUS to run, we start a dbus session
117 # and bind it to both the system and session buses
118 installCheckPhase = ''
119 runHook preInstallCheck
120
121 echo "<busconfig>
122 <type>session</type>
123 <listen>unix:tmpdir=$TMPDIR</listen>
124 <listen>unix:path=/build/system_bus_socket</listen>
125 <standard_session_servicedirs/>
126 <policy context=\"default\">
127 <!-- Allow everything to be sent -->
128 <allow send_destination=\"*\" eavesdrop=\"true\"/>
129 <!-- Allow everything to be received -->
130 <allow eavesdrop=\"true\"/>
131 <!-- Allow anyone to own anything -->
132 <allow own=\"*\"/>
133 </policy>
134 </busconfig>" > dbus.cfg
135 PATH=${
136 lib.makeBinPath (
137 [
138 dbus
139 procps
140 ]
141 ++ maybeXmodmap
142 )
143 }:$PATH \
144 USER="$(id -u -n)" \
145 DBUS_SYSTEM_BUS_ADDRESS=unix:path=/build/system_bus_socket \
146 ${dbus}/bin/dbus-run-session --config-file dbus.cfg \
147 python tests/test.py --start-dir unit
148
149 runHook postInstallCheck
150 '';
151
152 # Nixpkgs 15.9.4.3. When using wrapGAppsHook3 with special derivers you can end up with double wrapped binaries.
153 dontWrapGApps = true;
154
155 preFixup = ''
156 makeWrapperArgs+=(
157 "''${gappsWrapperArgs[@]}"
158 --prefix PATH : "${lib.makeBinPath maybeXmodmap}"
159 )
160 '';
161
162 passthru.tests = nixosTests.input-remapper;
163
164 meta = {
165 description = "Easy to use tool to change the mapping of your input device buttons";
166 homepage = "https://github.com/sezanzeb/input-remapper";
167 license = lib.licenses.gpl3Plus;
168 platforms = lib.platforms.linux;
169 maintainers = with lib.maintainers; [ LunNova ];
170 mainProgram = "input-remapper-gtk";
171 };
172}).overrideAttrs
173 (
174 final: prev: {
175 # Set in an override as buildPythonApplication doesn't yet support
176 # the `final:` arg yet from #119942 'overlay style overridable recursive attributes'
177 # this ensures the rev matches the input src's rev after overriding
178 # See https://discourse.nixos.org/t/avoid-rec-expresions-in-nixpkgs/8293/7 for more
179 # discussion
180 postPatch = prev.postPatch or "" + ''
181 # set revision for --version output
182 echo "COMMIT_HASH = '${final.src.rev}'" > inputremapper/commit_hash.py
183 '';
184 }
185 )