fusuma-plugin-remap 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +70 -0
- data/lib/fusuma/plugin/inputs/remap_keyboard_input.rb +2 -5
- data/lib/fusuma/plugin/inputs/remap_keyboard_input.yml +2 -1
- data/lib/fusuma/plugin/inputs/remap_touchpad_input.rb +4 -5
- data/lib/fusuma/plugin/inputs/remap_touchpad_input.yml +3 -1
- data/lib/fusuma/plugin/remap/keyboard_remapper.rb +5 -4
- data/lib/fusuma/plugin/remap/touchpad_remapper.rb +27 -16
- data/lib/fusuma/plugin/remap/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13ff7a06cbeae8f56ebc57ffbc347fe6adf2d7dba7b9fab4977047be9786aebc
|
4
|
+
data.tar.gz: 80a99b69509058b34c58fcea076be99b881a008193bbfb7065134c2d4f75291b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed14e66220bb7a483c666f777f2a17cbdd2d0be0ca8b0659f28ca2259d310ac7601f3280f2601ffc4fb809e87d7b37875c352e8cf01d92587e23123fe79f0be6
|
7
|
+
data.tar.gz: 97faa8067e4a49ba9821298a2347d2e3b6ce18a0137f2af1a718ea1a2d5e543a0bb089e081b6544d9375977f498079547d9f657c089730753cf58874a587c808
|
data/README.md
CHANGED
@@ -86,6 +86,76 @@ plugin:
|
|
86
86
|
This configuration allows you to specify which keys will trigger the emergency stop functionality.
|
87
87
|
It is important to verify this keybind to ensure a swift response during unexpected situations.
|
88
88
|
|
89
|
+
### Input Device Detection
|
90
|
+
|
91
|
+
#### Keyboard
|
92
|
+
|
93
|
+
configure `plugin.inputs.remap_keyboard_input` in `~/.config/fusuma/config.yml` to specify which physical keyboard to remap.
|
94
|
+
|
95
|
+
If your external or built-in keyboard is not detected, run `libinput list-devices` to find its name and add a matching pattern under `keyboard_name_patterns`.
|
96
|
+
|
97
|
+
```yaml
|
98
|
+
plugin:
|
99
|
+
inputs:
|
100
|
+
remap_keyboard_input:
|
101
|
+
# By default, Fusuma will detect physical keyboards matching these patterns.
|
102
|
+
# You can specify multiple regular‐expression strings in an array.
|
103
|
+
keyboard_name_patterns:
|
104
|
+
# Default value
|
105
|
+
- keyboard|Keyboard|KEYBOARD
|
106
|
+
|
107
|
+
# Emergency stop key combination.
|
108
|
+
# Specify exactly two keys joined by '+'.
|
109
|
+
emergency_ungrab_keys: RIGHTCTRL+LEFTCTRL
|
110
|
+
```
|
111
|
+
|
112
|
+
You can customize `keyboard_name_patterns` like this:
|
113
|
+
|
114
|
+
```yaml
|
115
|
+
plugin:
|
116
|
+
inputs:
|
117
|
+
remap_keyboard_input:
|
118
|
+
keyboard_name_patterns:
|
119
|
+
- xremap # Virtual keyboard created by another remapper
|
120
|
+
- PFU Limited HHKB-Hybrid # External keyboard
|
121
|
+
- keyboard|Keyboard|KEYBOARD # Default pattern
|
122
|
+
```
|
123
|
+
|
124
|
+
If your keyboard isn’t detected, run:
|
125
|
+
|
126
|
+
```sh
|
127
|
+
libinput list-devices
|
128
|
+
```
|
129
|
+
|
130
|
+
and add a suitable name pattern.
|
131
|
+
|
132
|
+
#### Touchpad
|
133
|
+
|
134
|
+
To specify touchpad name, configure `plugin.inputs.remap_touchpad_input`:
|
135
|
+
|
136
|
+
```yaml
|
137
|
+
plugin:
|
138
|
+
inputs:
|
139
|
+
remap_touchpad_input:
|
140
|
+
# By default, Fusuma will detect physical touchpads matching these patterns.
|
141
|
+
touchpad_name_patterns:
|
142
|
+
# Default values
|
143
|
+
- touchpad|Touchpad|TOUCHPAD
|
144
|
+
- trackpad|Trackpad|TRACKPAD
|
145
|
+
```
|
146
|
+
|
147
|
+
You can customize `touchpad_name_patterns` like this:
|
148
|
+
|
149
|
+
```yaml
|
150
|
+
plugin:
|
151
|
+
inputs:
|
152
|
+
remap_touchpad_input:
|
153
|
+
touchpad_name_patterns:
|
154
|
+
- Apple Inc. Magic Trackpad # External Trackpad
|
155
|
+
- your touchpad device name # Any other touchpad
|
156
|
+
- Touchpad|Trackpad # match to "Touchpad" or "Trackpad"
|
157
|
+
```
|
158
|
+
|
89
159
|
## Contributing
|
90
160
|
|
91
161
|
Bug reports and pull requests are welcome on GitHub at https://github.com/iberianpig/fusuma-plugin-remap. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "fusuma/device"
|
4
3
|
require_relative "../remap/keyboard_remapper"
|
5
4
|
require_relative "../remap/layer_manager"
|
6
5
|
|
@@ -14,8 +13,7 @@ module Fusuma
|
|
14
13
|
def config_param_types
|
15
14
|
{
|
16
15
|
emergency_ungrab_keys: [String],
|
17
|
-
keyboard_name_patterns: [Array, String]
|
18
|
-
touchpad_name_patterns: [Array, String]
|
16
|
+
keyboard_name_patterns: [Array, String]
|
19
17
|
}
|
20
18
|
end
|
21
19
|
|
@@ -49,8 +47,7 @@ module Fusuma
|
|
49
47
|
def setup_remapper
|
50
48
|
config = {
|
51
49
|
emergency_ungrab_keys: config_params(:emergency_ungrab_keys),
|
52
|
-
keyboard_name_patterns: config_params(:keyboard_name_patterns)
|
53
|
-
touchpad_name_patterns: config_params(:touchpad_name_patterns)
|
50
|
+
keyboard_name_patterns: config_params(:keyboard_name_patterns)
|
54
51
|
}
|
55
52
|
|
56
53
|
layer_manager = Remap::LayerManager.instance
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "fusuma/device"
|
4
3
|
require_relative "../remap/touchpad_remapper"
|
5
4
|
# require_relative "../remap/layer_manager"
|
6
5
|
|
@@ -63,14 +62,14 @@ module Fusuma
|
|
63
62
|
private
|
64
63
|
|
65
64
|
def setup_remapper
|
66
|
-
|
67
|
-
if
|
65
|
+
source_touchpads = TouchpadSelector.new(config_params(:touchpad_name_patterns)).select
|
66
|
+
if source_touchpads.empty?
|
68
67
|
MultiLogger.error("No touchpad found: #{config_params(:touchpad_name_patterns)}")
|
69
68
|
exit
|
70
69
|
end
|
71
70
|
|
72
71
|
MultiLogger.info("set up remapper")
|
73
|
-
MultiLogger.info("
|
72
|
+
MultiLogger.info("touchpad: #{source_touchpads}")
|
74
73
|
|
75
74
|
# layer_manager = Remap::LayerManager.instance
|
76
75
|
|
@@ -83,7 +82,7 @@ module Fusuma
|
|
83
82
|
remapper = Remap::TouchpadRemapper.new(
|
84
83
|
# layer_manager: layer_manager,
|
85
84
|
fusuma_writer: fusuma_writer,
|
86
|
-
|
85
|
+
source_touchpads: source_touchpads
|
87
86
|
)
|
88
87
|
remapper.run
|
89
88
|
end
|
@@ -3,6 +3,7 @@ require "msgpack"
|
|
3
3
|
require "set"
|
4
4
|
require_relative "layer_manager"
|
5
5
|
require_relative "uinput_keyboard"
|
6
|
+
require "fusuma/device"
|
6
7
|
|
7
8
|
module Fusuma
|
8
9
|
module Plugin
|
@@ -181,7 +182,7 @@ module Fusuma
|
|
181
182
|
|
182
183
|
# @param [Array<Revdev::EventDevice>] keyboards
|
183
184
|
def set_trap(keyboards)
|
184
|
-
@destroy = lambda do
|
185
|
+
@destroy = lambda do |status = 0|
|
185
186
|
keyboards.each do |kbd|
|
186
187
|
kbd.ungrab
|
187
188
|
rescue Errno::EINVAL
|
@@ -195,11 +196,11 @@ module Fusuma
|
|
195
196
|
# already destroyed
|
196
197
|
end
|
197
198
|
|
198
|
-
exit
|
199
|
+
exit status
|
199
200
|
end
|
200
201
|
|
201
202
|
Signal.trap(:INT) { @destroy.call }
|
202
|
-
Signal.trap(:TERM) { @destroy.call }
|
203
|
+
Signal.trap(:TERM) { @destroy.call(1) }
|
203
204
|
end
|
204
205
|
|
205
206
|
# Emergency stop keybind for virtual keyboard
|
@@ -309,7 +310,7 @@ module Fusuma
|
|
309
310
|
|
310
311
|
# Devices to detect key presses and releases
|
311
312
|
class KeyboardSelector
|
312
|
-
def initialize(names
|
313
|
+
def initialize(names)
|
313
314
|
@names = names
|
314
315
|
end
|
315
316
|
|
@@ -13,11 +13,15 @@ module Fusuma
|
|
13
13
|
VIRTUAL_TOUCHPAD_NAME = "fusuma_virtual_touchpad"
|
14
14
|
|
15
15
|
# @param fusuma_writer [IO]
|
16
|
-
# @param
|
17
|
-
def initialize(fusuma_writer:,
|
18
|
-
@
|
16
|
+
# @param source_touchpads [Revdev::Device]
|
17
|
+
def initialize(fusuma_writer:, source_touchpads:)
|
18
|
+
@source_touchpads = source_touchpads # original touchpad
|
19
19
|
@fusuma_writer = fusuma_writer # write event to fusuma_input
|
20
|
-
|
20
|
+
|
21
|
+
# FIXME: PalmDetection should be initialized with each touchpad
|
22
|
+
@palm_detectors = @source_touchpads.each_with_object({}) do |source_touchpad, palm_detectors|
|
23
|
+
palm_detectors[source_touchpad] = PalmDetection.new(source_touchpad)
|
24
|
+
end
|
21
25
|
|
22
26
|
set_trap
|
23
27
|
end
|
@@ -31,7 +35,10 @@ module Fusuma
|
|
31
35
|
mt_slot = 0
|
32
36
|
finger_state = nil
|
33
37
|
loop do
|
34
|
-
IO.select(
|
38
|
+
ios = IO.select(@source_touchpads.map(&:file)) # , @layer_manager.reader])
|
39
|
+
io = ios&.first&.first
|
40
|
+
|
41
|
+
touchpad = @source_touchpads.find { |t| t.file == io }
|
35
42
|
|
36
43
|
## example of input_event
|
37
44
|
# Event: time 1698456258.380027, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), value 43679
|
@@ -51,7 +58,7 @@ module Fusuma
|
|
51
58
|
# Event: time 1698456258.382693, type 1 (EV_KEY), code 333 (BTN_TOOL_DOUBLETAP), value 1
|
52
59
|
# Event: time 1698456258.382693, type 4 (EV_MSC), code 5 (MSC_TIMESTAMP), value 7100
|
53
60
|
# Event: time 1698456258.382693, -------------- SYN_REPORT ------------
|
54
|
-
input_event =
|
61
|
+
input_event = touchpad.read_input_event
|
55
62
|
|
56
63
|
touch_state[mt_slot] ||= {MT_TRACKING_ID: nil, X: nil, Y: nil, valid_touch_point: false}
|
57
64
|
syn_report = nil
|
@@ -71,14 +78,16 @@ module Fusuma
|
|
71
78
|
touch_state[mt_slot][:X] = input_event.value
|
72
79
|
when Revdev::ABS_MT_POSITION_Y
|
73
80
|
touch_state[mt_slot][:Y] = input_event.value
|
74
|
-
when Revdev::ABS_X, Revdev::ABS_Y
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
81
|
+
when Revdev::ABS_X, Revdev::ABS_Y,
|
82
|
+
Revdev::ABS_MT_PRESSURE,
|
83
|
+
Revdev::ABS_MT_TOOL_TYPE,
|
84
|
+
Revdev::ABS_MT_TOUCH_MAJOR,
|
85
|
+
Revdev::ABS_MT_TOUCH_MINOR,
|
86
|
+
Revdev::ABS_MT_ORIENTATION,
|
87
|
+
Revdev::ABS_PRESSURE
|
79
88
|
# ignore
|
80
89
|
else
|
81
|
-
|
90
|
+
MultiLogger.warn "unhandled event: #{input_event.hr_type}, #{input_event.hr_code}, #{input_event.value}"
|
82
91
|
end
|
83
92
|
when Revdev::EV_KEY
|
84
93
|
case input_event.code
|
@@ -108,21 +117,22 @@ module Fusuma
|
|
108
117
|
when Revdev::SYN_DROPPED
|
109
118
|
MultiLogger.error "Dropped: #{input_event.value}"
|
110
119
|
else
|
111
|
-
raise "unhandled event
|
120
|
+
raise "unhandled event: #{input_event.hr_type}, #{input_event.hr_code}, #{input_event.value}"
|
112
121
|
end
|
113
122
|
else
|
114
|
-
raise "unhandled event
|
123
|
+
raise "unhandled event: #{input_event.hr_type}, #{input_event.hr_code}, #{input_event.value}"
|
115
124
|
end
|
116
125
|
|
117
126
|
# TODO:
|
118
127
|
# Remember the most recent valid touch position and exclude it if it is close to that position
|
119
128
|
# For example, when dragging, it is possible to touch around the edge of the touchpad again after reaching the edge of the touchpad, so in that case, you do not want to execute palm detection
|
120
129
|
if touch_state[mt_slot][:valid_touch_point] != true
|
121
|
-
touch_state[mt_slot][:valid_touch_point] = @
|
130
|
+
touch_state[mt_slot][:valid_touch_point] = @palm_detectors[touchpad].palm?(touch_state[mt_slot])
|
122
131
|
end
|
123
132
|
|
124
133
|
if syn_report
|
125
134
|
# TODO: define format as fusuma_input
|
135
|
+
# TODO: Add data to identify multiple touchpads
|
126
136
|
data = {finger: finger_state, touch_state: touch_state}
|
127
137
|
@fusuma_writer.write(data.to_msgpack)
|
128
138
|
end
|
@@ -141,7 +151,8 @@ module Fusuma
|
|
141
151
|
|
142
152
|
def create_virtual_touchpad
|
143
153
|
MultiLogger.info "Create virtual touchpad: #{VIRTUAL_TOUCHPAD_NAME}"
|
144
|
-
|
154
|
+
# NOTE: Use uinput to create a virtual touchpad that copies from first touchpad
|
155
|
+
uinput.create_from_device(name: VIRTUAL_TOUCHPAD_NAME, device: @source_touchpads.first)
|
145
156
|
end
|
146
157
|
|
147
158
|
def set_trap
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fusuma-plugin-remap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- iberianpig
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-05-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fusuma
|