fusuma-plugin-remap 0.11.1 → 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 +75 -59
- 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
|
|
@@ -12,6 +13,7 @@ module Fusuma
|
|
|
12
13
|
include Revdev
|
|
13
14
|
|
|
14
15
|
VIRTUAL_KEYBOARD_NAME = "fusuma_virtual_keyboard"
|
|
16
|
+
DEFAULT_EMERGENCY_KEYBIND = "RIGHTCTRL+LEFTCTRL".freeze
|
|
15
17
|
|
|
16
18
|
# Key conversion tables for better performance and readability
|
|
17
19
|
KEYMAP = Revdev.constants.select { |c| c.start_with?("KEY_", "BTN_") }
|
|
@@ -80,25 +82,39 @@ module Fusuma
|
|
|
80
82
|
end
|
|
81
83
|
|
|
82
84
|
remapped = current_mapping.fetch(input_key.to_sym, nil)
|
|
83
|
-
|
|
85
|
+
case remapped
|
|
86
|
+
when String, Symbol
|
|
87
|
+
# Remapped to another key - continue processing below
|
|
88
|
+
when Hash
|
|
89
|
+
# Command execution (e.g., {:SENDKEY=>"LEFTCTRL+BTN_LEFT", :CLEARMODIFIERS=>true})
|
|
90
|
+
# Skip input event processing and let Fusuma's Executor handle this
|
|
91
|
+
next
|
|
92
|
+
when nil
|
|
93
|
+
# Not remapped - write original key event as-is
|
|
84
94
|
uinput_keyboard.write_input_event(input_event)
|
|
85
95
|
next
|
|
96
|
+
else
|
|
97
|
+
# Invalid remapping configuration
|
|
98
|
+
MultiLogger.warn("Invalid remapped value - type: #{remapped.class}, key: #{input_key}")
|
|
99
|
+
next
|
|
86
100
|
end
|
|
87
101
|
|
|
88
102
|
remapped_code = key_to_code(remapped)
|
|
89
103
|
if remapped_code.nil?
|
|
90
|
-
MultiLogger.warn("Invalid remapped key: #{remapped},
|
|
104
|
+
MultiLogger.warn("Invalid remapped value - unknown key: #{remapped}, input: #{input_key}")
|
|
91
105
|
uinput_keyboard.write_input_event(input_event)
|
|
92
106
|
next
|
|
93
107
|
end
|
|
94
108
|
|
|
95
109
|
remapped_event = InputEvent.new(nil, input_event.type, remapped_code, input_event.value)
|
|
96
110
|
|
|
97
|
-
# Workaround
|
|
98
|
-
#
|
|
99
|
-
|
|
100
|
-
# set original key before remapping
|
|
111
|
+
# Workaround: If a key was pressed before remapping started and is being released,
|
|
112
|
+
# use the original key code to ensure proper key release
|
|
113
|
+
if should_use_original_key?(remapped, remapped_event.value)
|
|
101
114
|
remapped_event.code = input_event.code
|
|
115
|
+
else
|
|
116
|
+
# Only update virtual key state if we're using the remapped key
|
|
117
|
+
update_virtual_key_state(remapped, remapped_event.value)
|
|
102
118
|
end
|
|
103
119
|
|
|
104
120
|
# remap to command will be nil
|
|
@@ -140,21 +156,34 @@ module Fusuma
|
|
|
140
156
|
@pressed_virtual_keys ||= Set.new
|
|
141
157
|
end
|
|
142
158
|
|
|
143
|
-
#
|
|
159
|
+
# Update virtual keyboard key state
|
|
144
160
|
# @param [String] remapped_value remapped key name
|
|
145
|
-
# @param [Integer] event_value event value
|
|
146
|
-
# @return [
|
|
147
|
-
|
|
148
|
-
def record_virtual_keyboard_event?(remapped_value, event_value)
|
|
161
|
+
# @param [Integer] event_value event value (0: release, 1: press, 2: repeat)
|
|
162
|
+
# @return [void]
|
|
163
|
+
def update_virtual_key_state(remapped_value, event_value)
|
|
149
164
|
case event_value
|
|
150
|
-
when 0
|
|
151
|
-
pressed_virtual_keys.delete
|
|
152
|
-
when 1
|
|
153
|
-
pressed_virtual_keys.add
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
165
|
+
when 0 # key release
|
|
166
|
+
pressed_virtual_keys.delete(remapped_value)
|
|
167
|
+
when 1 # key press
|
|
168
|
+
pressed_virtual_keys.add(remapped_value)
|
|
169
|
+
# when 2 is repeat - no state change needed
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Check if we should use the original key code instead of remapped key
|
|
174
|
+
# This handles the case where a key was pressed before remapping started
|
|
175
|
+
# and is released after remapping
|
|
176
|
+
# @param [String] remapped_value remapped key name
|
|
177
|
+
# @param [Integer] event_value event value (0: release, 1: press, 2: repeat)
|
|
178
|
+
# @return [Boolean] true if we should use original key code
|
|
179
|
+
def should_use_original_key?(remapped_value, event_value)
|
|
180
|
+
case event_value
|
|
181
|
+
when 0 # key release
|
|
182
|
+
# If the key was not in our pressed set, it means it was pressed
|
|
183
|
+
# before remapping started, so we should use original key
|
|
184
|
+
!pressed_virtual_keys.include?(remapped_value)
|
|
185
|
+
when 1, 2 # key press or repeat
|
|
186
|
+
false # Always use remapped key for press/repeat events
|
|
158
187
|
end
|
|
159
188
|
end
|
|
160
189
|
|
|
@@ -164,29 +193,36 @@ module Fusuma
|
|
|
164
193
|
|
|
165
194
|
def create_virtual_keyboard
|
|
166
195
|
touchpad_name_patterns = @config[:touchpad_name_patterns]
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
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
|
|
173
201
|
|
|
174
202
|
MultiLogger.info "Create virtual keyboard: #{VIRTUAL_KEYBOARD_NAME}"
|
|
175
203
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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
|
|
190
226
|
end
|
|
191
227
|
|
|
192
228
|
def grab_keyboards(keyboards)
|
|
@@ -224,8 +260,6 @@ module Fusuma
|
|
|
224
260
|
Signal.trap(:TERM) { @destroy.call(1) }
|
|
225
261
|
end
|
|
226
262
|
|
|
227
|
-
DEFAULT_EMERGENCY_KEYBIND = "RIGHTCTRL+LEFTCTRL".freeze
|
|
228
|
-
|
|
229
263
|
# Emergency stop keybind for virtual keyboard
|
|
230
264
|
def set_emergency_ungrab_keys(keybind_string)
|
|
231
265
|
keybinds = keybind_string&.split("+")
|
|
@@ -369,24 +403,6 @@ module Fusuma
|
|
|
369
403
|
sleep 3
|
|
370
404
|
end
|
|
371
405
|
end
|
|
372
|
-
|
|
373
|
-
class TouchpadSelector
|
|
374
|
-
def initialize(names = nil)
|
|
375
|
-
@names = names
|
|
376
|
-
end
|
|
377
|
-
|
|
378
|
-
# @return [Array<Revdev::EventDevice>]
|
|
379
|
-
def select
|
|
380
|
-
devices = if @names
|
|
381
|
-
Fusuma::Device.all.select { |d| Array(@names).any? { |name| d.name =~ /#{name}/ } }
|
|
382
|
-
else
|
|
383
|
-
# available returns only touchpad devices
|
|
384
|
-
Fusuma::Device.available
|
|
385
|
-
end
|
|
386
|
-
|
|
387
|
-
devices.map { |d| Revdev::EventDevice.new("/dev/input/#{d.id}") }
|
|
388
|
-
end
|
|
389
|
-
end
|
|
390
406
|
end
|
|
391
407
|
end
|
|
392
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
|