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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 71eb89bd5884a491b87dc36ad65728e1069c9073ad9b1971ae989ed3cfad2e3f
4
- data.tar.gz: 43dcf898d9ef9775e0d42b037f1e87daa0d1d36b7a367bcabb7211ce05300e5f
3
+ metadata.gz: 13ff7a06cbeae8f56ebc57ffbc347fe6adf2d7dba7b9fab4977047be9786aebc
4
+ data.tar.gz: 80a99b69509058b34c58fcea076be99b881a008193bbfb7065134c2d4f75291b
5
5
  SHA512:
6
- metadata.gz: 8c5dd2a0bb627288f3ab2ba47f838f57022feb9786e0e99818a17201c57a7ca35a536b852200e44a7e700a86482cc17daf71594432cc89c6f22d7c90563301b8
7
- data.tar.gz: 3631827a2d5eb1924adfee909f5d1cc721554089f4c2350e33cb063a83dcafb1d282a1b635c5945a2b2e7c525e16692c39c105fc76b47700b3f714162c06b07b
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,7 +1,8 @@
1
1
  plugin:
2
2
  inputs:
3
3
  remap_keyboard_input:
4
- keyboard_name_patterns: ["keyboard", "Keyboard", "KEYBOARD"]
4
+ keyboard_name_patterns:
5
+ - keyboard|Keyboard|KEYBOARD
5
6
  emergency_ungrab_keys: RIGHTCTRL+LEFTCTRL
6
7
  buffers:
7
8
  keypress_buffer:
@@ -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
- internal_touchpad = TouchpadSelector.new(config_params(:touchpad_name_patterns)).select.first
67
- if internal_touchpad.nil?
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("internal_touchpad: #{internal_touchpad.device_name}")
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
- source_touchpad: internal_touchpad
85
+ source_touchpads: source_touchpads
87
86
  )
88
87
  remapper.run
89
88
  end
@@ -1,4 +1,6 @@
1
1
  plugin:
2
2
  inputs:
3
3
  remap_touchpad_input:
4
- touchpad_name_patterns: ["touchpad", "Touchpad", "TOUCHPAD"]
4
+ touchpad_name_patterns:
5
+ - touchpad|Touchpad|TOUCHPAD
6
+ - trackpad|Trackpad|TRACKPAD
@@ -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 0
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 = ["keyboard", "Keyboard", "KEYBOARD"])
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 source_touchpad [Revdev::Device]
17
- def initialize(fusuma_writer:, source_touchpad:)
18
- @source_touchpad = source_touchpad # original touchpad
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
- @palm_detector ||= PalmDetection.new(source_touchpad)
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([@source_touchpad.file]) # , @layer_manager.reader])
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 = @source_touchpad.read_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
- # ignore
76
- when Revdev::ABS_MT_PRESSURE
77
- # ignore
78
- when Revdev::ABS_MT_TOOL_TYPE
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
- raise "unhandled event"
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", "#{input_event.hr_type}, #{input_event.hr_code}, #{input_event.value}"
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", "#{input_event.hr_type}, #{input_event.hr_code}, #{input_event.value}"
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] = @palm_detector.palm?(touch_state[mt_slot])
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
- uinput.create_from_device(name: VIRTUAL_TOUCHPAD_NAME, device: @source_touchpad)
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
@@ -3,7 +3,7 @@
3
3
  module Fusuma
4
4
  module Plugin
5
5
  module Remap
6
- VERSION = "0.9.0"
6
+ VERSION = "0.10.0"
7
7
  end
8
8
  end
9
9
  end
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.9.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-02-19 00:00:00.000000000 Z
11
+ date: 2025-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fusuma