fusuma-plugin-remap 0.11.2 → 0.12.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/fusuma-plugin-remap.gemspec +1 -1
- data/lib/fusuma/plugin/inputs/remap_touchpad_input.rb +15 -28
- data/lib/fusuma/plugin/remap/device_selector.rb +62 -0
- data/lib/fusuma/plugin/remap/keyboard_remapper.rb +28 -38
- data/lib/fusuma/plugin/remap/touchpad_remapper.rb +45 -1
- data/lib/fusuma/plugin/remap/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 22d4ef7f153876d648359c14463da56777ecc7878cac97f79d1e29784a6673e8
|
|
4
|
+
data.tar.gz: f4381c0dcc9c5277fdeb14f0a19ee49772a3a06b07adfd9a31e0f43f5fff99a2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a8111498a2c1d85caaf3a3c03af770c308f4e1b4c395a739f14e7832fd91280755b65424a9626a700b411112ab54b25a27f61a2d37aa64daf460573a3a4fe925
|
|
7
|
+
data.tar.gz: 54b0014a0f13b5a040f284ba8c3f87ecde1729ac0643b1fcb9d17411dfa9f1cd79ed03c8aa24dfeed2c2856df47ac76e69970eddba433b09a223bd695635edb2
|
data/fusuma-plugin-remap.gemspec
CHANGED
|
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
|
|
|
24
24
|
# https://packages.ubuntu.com/search?keywords=ruby&searchon=names&exact=1&suite=all§ion=main
|
|
25
25
|
# support focal (20.04LTS) 2.7
|
|
26
26
|
|
|
27
|
-
spec.add_dependency "fusuma", ">= 3.
|
|
27
|
+
spec.add_dependency "fusuma", ">= 3.11.0"
|
|
28
28
|
spec.add_dependency "fusuma-plugin-keypress", ">= 0.11.0"
|
|
29
29
|
spec.add_dependency "fusuma-plugin-sendkey", ">= 0.12.0"
|
|
30
30
|
spec.add_dependency "msgpack"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "../remap/touchpad_remapper"
|
|
4
|
+
require_relative "../remap/device_selector"
|
|
4
5
|
|
|
5
6
|
module Fusuma
|
|
6
7
|
module Plugin
|
|
@@ -46,51 +47,37 @@ module Fusuma
|
|
|
46
47
|
private
|
|
47
48
|
|
|
48
49
|
def setup_remapper
|
|
49
|
-
source_touchpads = TouchpadSelector.new(config_params(:touchpad_name_patterns)).select
|
|
50
|
-
if source_touchpads.empty?
|
|
51
|
-
MultiLogger.error("No touchpad found: #{config_params(:touchpad_name_patterns)}")
|
|
52
|
-
exit
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
MultiLogger.info("set up remapper")
|
|
56
|
-
MultiLogger.info("touchpad: #{source_touchpads}")
|
|
57
|
-
|
|
58
50
|
# layer_manager = Remap::LayerManager.instance
|
|
59
51
|
|
|
60
52
|
# physical touchpad input event
|
|
61
53
|
@fusuma_reader, fusuma_writer = IO.pipe
|
|
54
|
+
touchpad_name_patterns = config_params(:touchpad_name_patterns)
|
|
62
55
|
|
|
63
56
|
fork do
|
|
64
57
|
# layer_manager.writer.close
|
|
65
58
|
@fusuma_reader.close
|
|
59
|
+
|
|
60
|
+
# DeviceSelector waits until touchpad is found (like KeyboardSelector)
|
|
61
|
+
# NOTE: This must be inside fork to avoid blocking the main Fusuma process
|
|
62
|
+
source_touchpads = Remap::DeviceSelector.new(
|
|
63
|
+
name_patterns: touchpad_name_patterns,
|
|
64
|
+
device_type: :touchpad
|
|
65
|
+
).select(wait: true)
|
|
66
|
+
|
|
67
|
+
MultiLogger.info("set up remapper")
|
|
68
|
+
MultiLogger.info("touchpad: #{source_touchpads}")
|
|
69
|
+
|
|
66
70
|
remapper = Remap::TouchpadRemapper.new(
|
|
67
71
|
# layer_manager: layer_manager,
|
|
68
72
|
fusuma_writer: fusuma_writer,
|
|
69
|
-
source_touchpads: source_touchpads
|
|
73
|
+
source_touchpads: source_touchpads,
|
|
74
|
+
touchpad_name_patterns: touchpad_name_patterns
|
|
70
75
|
)
|
|
71
76
|
remapper.run
|
|
72
77
|
end
|
|
73
78
|
# layer_manager.reader.close
|
|
74
79
|
fusuma_writer.close
|
|
75
80
|
end
|
|
76
|
-
|
|
77
|
-
class TouchpadSelector
|
|
78
|
-
def initialize(names = nil)
|
|
79
|
-
@names = names
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# @return [Array<Revdev::EventDevice>]
|
|
83
|
-
def select
|
|
84
|
-
devices = if @names
|
|
85
|
-
Fusuma::Device.all.select { |d| Array(@names).any? { |name| d.name =~ /#{name}/ } }
|
|
86
|
-
else
|
|
87
|
-
# available returns only touchpad devices
|
|
88
|
-
Fusuma::Device.available
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
devices.map { |d| Revdev::EventDevice.new("/dev/input/#{d.id}") }
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
81
|
end
|
|
95
82
|
end
|
|
96
83
|
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "revdev"
|
|
4
|
+
require "fusuma/device"
|
|
5
|
+
|
|
6
|
+
module Fusuma
|
|
7
|
+
module Plugin
|
|
8
|
+
module Remap
|
|
9
|
+
# Common device selector for touchpad and keyboard detection
|
|
10
|
+
# Unifies TouchpadSelector implementations across the codebase
|
|
11
|
+
class DeviceSelector
|
|
12
|
+
POLL_INTERVAL = 3 # seconds
|
|
13
|
+
|
|
14
|
+
# @param name_patterns [Array, String, nil] patterns for device names
|
|
15
|
+
# @param device_type [Symbol] :touchpad or :keyboard (for logging)
|
|
16
|
+
def initialize(name_patterns: nil, device_type: :touchpad)
|
|
17
|
+
@name_patterns = name_patterns
|
|
18
|
+
@device_type = device_type
|
|
19
|
+
@displayed_waiting = false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Select devices that match the name patterns
|
|
23
|
+
# @param wait [Boolean] if true, wait until device is found (polling loop)
|
|
24
|
+
# @return [Array<Revdev::EventDevice>]
|
|
25
|
+
def select(wait: false)
|
|
26
|
+
loop do
|
|
27
|
+
Fusuma::Device.reset # reset cache to get the latest device information
|
|
28
|
+
devices = find_devices
|
|
29
|
+
return to_event_devices(devices) unless devices.empty?
|
|
30
|
+
return [] unless wait
|
|
31
|
+
|
|
32
|
+
log_waiting_message unless @displayed_waiting
|
|
33
|
+
sleep POLL_INTERVAL
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def find_devices
|
|
40
|
+
if @name_patterns
|
|
41
|
+
Fusuma::Device.all.select { |d|
|
|
42
|
+
Array(@name_patterns).any? { |name| d.name =~ /#{name}/ }
|
|
43
|
+
}
|
|
44
|
+
else
|
|
45
|
+
# available returns only touchpad devices
|
|
46
|
+
Fusuma::Device.available
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def to_event_devices(devices)
|
|
51
|
+
devices.map { |d| Revdev::EventDevice.new("/dev/input/#{d.id}") }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def log_waiting_message
|
|
55
|
+
MultiLogger.warn "No #{@device_type} found: #{@name_patterns || "(default patterns)"}"
|
|
56
|
+
MultiLogger.warn "Waiting for #{@device_type} to be connected..."
|
|
57
|
+
@displayed_waiting = true
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
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_relative "device_selector"
|
|
6
7
|
require "fusuma/device"
|
|
7
8
|
|
|
8
9
|
module Fusuma
|
|
@@ -192,29 +193,36 @@ module Fusuma
|
|
|
192
193
|
|
|
193
194
|
def create_virtual_keyboard
|
|
194
195
|
touchpad_name_patterns = @config[:touchpad_name_patterns]
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
end
|
|
196
|
+
# Use DeviceSelector without wait - keyboard remap should work even without touchpad
|
|
197
|
+
internal_touchpad = DeviceSelector.new(
|
|
198
|
+
name_patterns: touchpad_name_patterns,
|
|
199
|
+
device_type: :touchpad
|
|
200
|
+
).select(wait: false).first
|
|
201
201
|
|
|
202
202
|
MultiLogger.info "Create virtual keyboard: #{VIRTUAL_KEYBOARD_NAME}"
|
|
203
203
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
204
|
+
if internal_touchpad.nil?
|
|
205
|
+
MultiLogger.warn("No touchpad found: #{touchpad_name_patterns}")
|
|
206
|
+
MultiLogger.warn("Disable-while-typing feature will not work without a touchpad")
|
|
207
|
+
# Create virtual keyboard without touchpad device ID
|
|
208
|
+
# disable-while-typing will not work in this case
|
|
209
|
+
uinput_keyboard.create VIRTUAL_KEYBOARD_NAME
|
|
210
|
+
else
|
|
211
|
+
uinput_keyboard.create VIRTUAL_KEYBOARD_NAME,
|
|
212
|
+
Revdev::InputId.new(
|
|
213
|
+
# disable while typing is enabled when
|
|
214
|
+
# - Both the keyboard and touchpad are BUS_I8042
|
|
215
|
+
# - The touchpad and keyboard have the same vendor/product
|
|
216
|
+
# ref: (https://wayland.freedesktop.org/libinput/doc/latest/palm-detection.html#disable-while-typing)
|
|
217
|
+
#
|
|
218
|
+
{
|
|
219
|
+
bustype: Revdev::BUS_I8042,
|
|
220
|
+
vendor: internal_touchpad.device_id.vendor,
|
|
221
|
+
product: internal_touchpad.device_id.product,
|
|
222
|
+
version: internal_touchpad.device_id.version
|
|
223
|
+
}
|
|
224
|
+
)
|
|
225
|
+
end
|
|
218
226
|
end
|
|
219
227
|
|
|
220
228
|
def grab_keyboards(keyboards)
|
|
@@ -395,24 +403,6 @@ module Fusuma
|
|
|
395
403
|
sleep 3
|
|
396
404
|
end
|
|
397
405
|
end
|
|
398
|
-
|
|
399
|
-
class TouchpadSelector
|
|
400
|
-
def initialize(names = nil)
|
|
401
|
-
@names = names
|
|
402
|
-
end
|
|
403
|
-
|
|
404
|
-
# @return [Array<Revdev::EventDevice>]
|
|
405
|
-
def select
|
|
406
|
-
devices = if @names
|
|
407
|
-
Fusuma::Device.all.select { |d| Array(@names).any? { |name| d.name =~ /#{name}/ } }
|
|
408
|
-
else
|
|
409
|
-
# available returns only touchpad devices
|
|
410
|
-
Fusuma::Device.available
|
|
411
|
-
end
|
|
412
|
-
|
|
413
|
-
devices.map { |d| Revdev::EventDevice.new("/dev/input/#{d.id}") }
|
|
414
|
-
end
|
|
415
|
-
end
|
|
416
406
|
end
|
|
417
407
|
end
|
|
418
408
|
end
|
|
@@ -3,6 +3,8 @@ require "msgpack"
|
|
|
3
3
|
require "set"
|
|
4
4
|
|
|
5
5
|
require_relative "uinput_touchpad"
|
|
6
|
+
require_relative "device_selector"
|
|
7
|
+
require "fusuma/device"
|
|
6
8
|
|
|
7
9
|
module Fusuma
|
|
8
10
|
module Plugin
|
|
@@ -14,9 +16,11 @@ module Fusuma
|
|
|
14
16
|
|
|
15
17
|
# @param fusuma_writer [IO]
|
|
16
18
|
# @param source_touchpads [Revdev::Device]
|
|
17
|
-
|
|
19
|
+
# @param touchpad_name_patterns [Array, String, nil] patterns for touchpad device names (for reconnection)
|
|
20
|
+
def initialize(fusuma_writer:, source_touchpads:, touchpad_name_patterns: nil)
|
|
18
21
|
@source_touchpads = source_touchpads # original touchpad
|
|
19
22
|
@fusuma_writer = fusuma_writer # write event to fusuma_input
|
|
23
|
+
@touchpad_name_patterns = touchpad_name_patterns # for reconnection
|
|
20
24
|
|
|
21
25
|
@palm_detectors = @source_touchpads.each_with_object({}) do |source_touchpad, palm_detectors|
|
|
22
26
|
palm_detectors[source_touchpad] = PalmDetection.new(source_touchpad)
|
|
@@ -157,7 +161,19 @@ module Fusuma
|
|
|
157
161
|
prev_status = status
|
|
158
162
|
prev_valid_touch = valid_touch
|
|
159
163
|
end
|
|
164
|
+
rescue Errno::ENODEV => e
|
|
165
|
+
MultiLogger.error "Touchpad device is removed: #{e.message}"
|
|
166
|
+
MultiLogger.info "Waiting for touchpad to reconnect..."
|
|
167
|
+
reload_touchpads
|
|
168
|
+
touch_state = {}
|
|
169
|
+
mt_slot = 0
|
|
170
|
+
finger_state = nil
|
|
171
|
+
prev_valid_touch = false
|
|
172
|
+
prev_status = nil
|
|
173
|
+
retry
|
|
160
174
|
end
|
|
175
|
+
rescue IOError => e
|
|
176
|
+
MultiLogger.error "Touchpad IO error: #{e.message}"
|
|
161
177
|
rescue => e
|
|
162
178
|
MultiLogger.error "An error occurred: #{e.message}"
|
|
163
179
|
ensure
|
|
@@ -176,6 +192,34 @@ module Fusuma
|
|
|
176
192
|
uinput.create_from_device(name: VIRTUAL_TOUCHPAD_NAME, device: @source_touchpads.first)
|
|
177
193
|
end
|
|
178
194
|
|
|
195
|
+
# Reload touchpads after device disconnection
|
|
196
|
+
# This method waits until a touchpad is reconnected
|
|
197
|
+
def reload_touchpads
|
|
198
|
+
# Destroy virtual touchpad
|
|
199
|
+
begin
|
|
200
|
+
uinput.destroy
|
|
201
|
+
rescue IOError
|
|
202
|
+
# already destroyed
|
|
203
|
+
end
|
|
204
|
+
@uinput = nil
|
|
205
|
+
|
|
206
|
+
# Wait and detect touchpad using DeviceSelector
|
|
207
|
+
@source_touchpads = DeviceSelector.new(
|
|
208
|
+
name_patterns: @touchpad_name_patterns,
|
|
209
|
+
device_type: :touchpad
|
|
210
|
+
).select(wait: true)
|
|
211
|
+
|
|
212
|
+
# Reinitialize palm detectors
|
|
213
|
+
@palm_detectors = @source_touchpads.each_with_object({}) do |source_touchpad, palm_detectors|
|
|
214
|
+
palm_detectors[source_touchpad] = PalmDetection.new(source_touchpad)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# Recreate virtual touchpad
|
|
218
|
+
create_virtual_touchpad
|
|
219
|
+
|
|
220
|
+
MultiLogger.info "Touchpad reconnected: #{@source_touchpads}"
|
|
221
|
+
end
|
|
222
|
+
|
|
179
223
|
def set_trap
|
|
180
224
|
@destroy = lambda do
|
|
181
225
|
begin
|
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.12.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- iberianpig
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-01-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: fusuma
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version:
|
|
19
|
+
version: 3.11.0
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version:
|
|
26
|
+
version: 3.11.0
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: fusuma-plugin-keypress
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -120,6 +120,7 @@ files:
|
|
|
120
120
|
- lib/fusuma/plugin/inputs/remap_touchpad_input.rb
|
|
121
121
|
- lib/fusuma/plugin/inputs/remap_touchpad_input.yml
|
|
122
122
|
- lib/fusuma/plugin/remap.rb
|
|
123
|
+
- lib/fusuma/plugin/remap/device_selector.rb
|
|
123
124
|
- lib/fusuma/plugin/remap/keyboard_remapper.rb
|
|
124
125
|
- lib/fusuma/plugin/remap/layer_manager.rb
|
|
125
126
|
- lib/fusuma/plugin/remap/touchpad_remapper.rb
|