fusuma-plugin-remap 0.10.0 → 0.11.1
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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c1a6f601df78486fb3bf89f9c7902fe9fd46e45c33e2807eff9f0c4b5a38ec45
|
4
|
+
data.tar.gz: 50ca1d1da716e62d9ed9cc3973b201f9b8c93b00b5e313559bc5d7d4a73bfd3d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 881a29098c368a60f0d4469d77b1ffc118d0c9eb2df02d2b7c492ba356f30ab0ad740a73bfa96e229a1fd16d46a7a839139c7b4077e26fb30b092d0c142ca28c
|
7
|
+
data.tar.gz: 50dd4b8c9554ee17e338a5ded7248d1b4f9215d03ca5d19d5e2c8d97731687b42b1edb2105d7ebf7539ac2718bb3d3085db4c800db26cad54426be93fe854643
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "../remap/touchpad_remapper"
|
4
|
-
# require_relative "../remap/layer_manager"
|
5
4
|
|
6
5
|
module Fusuma
|
7
6
|
module Plugin
|
@@ -35,22 +34,7 @@ module Fusuma
|
|
35
34
|
|
36
35
|
gesture = "touch"
|
37
36
|
finger = data["finger"]
|
38
|
-
|
39
|
-
# @touch_state ||= {}
|
40
|
-
# @mt_slot ||= 0
|
41
|
-
# @touch_state[@mt_slot] ||= {
|
42
|
-
# MT_TRACKING_ID: nil,
|
43
|
-
# X: nil,
|
44
|
-
# Y: nil,
|
45
|
-
# valid_touch_point: false
|
46
|
-
# }
|
47
|
-
# TODO: implement update touch_state
|
48
|
-
status =
|
49
|
-
if data["touch_state"].any? { |_, v| v["valid_touch_point"] }
|
50
|
-
"begin"
|
51
|
-
else
|
52
|
-
"end"
|
53
|
-
end
|
37
|
+
status = data["status"]
|
54
38
|
|
55
39
|
Events::Records::GestureRecord.new(gesture: gesture, status: status, finger: finger, delta: nil)
|
56
40
|
rescue EOFError => e
|
@@ -13,6 +13,14 @@ module Fusuma
|
|
13
13
|
|
14
14
|
VIRTUAL_KEYBOARD_NAME = "fusuma_virtual_keyboard"
|
15
15
|
|
16
|
+
# Key conversion tables for better performance and readability
|
17
|
+
KEYMAP = Revdev.constants.select { |c| c.start_with?("KEY_", "BTN_") }
|
18
|
+
.map { |c| [Revdev.const_get(c), c.to_s.delete_prefix("KEY_")] }
|
19
|
+
.to_h.freeze
|
20
|
+
CODEMAP = Revdev.constants.select { |c| c.start_with?("KEY_", "BTN_") }
|
21
|
+
.map { |c| [c, Revdev.const_get(c)] }
|
22
|
+
.to_h.freeze
|
23
|
+
|
16
24
|
# @param layer_manager [Fusuma::Plugin::Remap::LayerManager]
|
17
25
|
# @param fusuma_writer [IO]
|
18
26
|
# @param config [Hash]
|
@@ -53,7 +61,7 @@ module Fusuma
|
|
53
61
|
end
|
54
62
|
|
55
63
|
input_event = @source_keyboards.find { |kbd| kbd.file == io }.read_input_event
|
56
|
-
input_key =
|
64
|
+
input_key = code_to_key(input_event.code)
|
57
65
|
|
58
66
|
if input_event.type == EV_KEY
|
59
67
|
@emergency_stop.call(old_ie, input_event)
|
@@ -61,7 +69,13 @@ module Fusuma
|
|
61
69
|
old_ie = input_event
|
62
70
|
if input_event.value != 2 # repeat
|
63
71
|
data = {key: input_key, status: input_event.value, layer: layer}
|
64
|
-
|
72
|
+
begin
|
73
|
+
@fusuma_writer.write(data.to_msgpack)
|
74
|
+
rescue IOError => e
|
75
|
+
MultiLogger.error("Failed to write to fusuma_writer: #{e.message}")
|
76
|
+
@destroy&.call(1)
|
77
|
+
return
|
78
|
+
end
|
65
79
|
end
|
66
80
|
end
|
67
81
|
|
@@ -71,7 +85,14 @@ module Fusuma
|
|
71
85
|
next
|
72
86
|
end
|
73
87
|
|
74
|
-
|
88
|
+
remapped_code = key_to_code(remapped)
|
89
|
+
if remapped_code.nil?
|
90
|
+
MultiLogger.warn("Invalid remapped key: #{remapped}, skipping...")
|
91
|
+
uinput_keyboard.write_input_event(input_event)
|
92
|
+
next
|
93
|
+
end
|
94
|
+
|
95
|
+
remapped_event = InputEvent.new(nil, input_event.type, remapped_code, input_event.value)
|
75
96
|
|
76
97
|
# Workaround to solve the problem that the remapped key remains pressed
|
77
98
|
# when the key pressed before remapping is released after remapping
|
@@ -203,28 +224,30 @@ module Fusuma
|
|
203
224
|
Signal.trap(:TERM) { @destroy.call(1) }
|
204
225
|
end
|
205
226
|
|
227
|
+
DEFAULT_EMERGENCY_KEYBIND = "RIGHTCTRL+LEFTCTRL".freeze
|
228
|
+
|
206
229
|
# Emergency stop keybind for virtual keyboard
|
207
230
|
def set_emergency_ungrab_keys(keybind_string)
|
208
231
|
keybinds = keybind_string&.split("+")
|
209
232
|
# TODO: Extract to a configuration file or make it optional
|
210
233
|
# it should stop other remappers
|
211
234
|
if keybinds&.size != 2
|
212
|
-
MultiLogger.
|
213
|
-
MultiLogger.
|
214
|
-
MultiLogger.
|
235
|
+
MultiLogger.warn "Invalid emergency ungrab keybinds: #{keybinds}, fallback to #{DEFAULT_EMERGENCY_KEYBIND}"
|
236
|
+
MultiLogger.warn "Please set two keys separated by '+'"
|
237
|
+
MultiLogger.warn <<~YAML
|
215
238
|
plugin:
|
216
239
|
inputs:
|
217
240
|
remap_keyboard_input:
|
218
241
|
emergency_ungrab_keys: RIGHTCTRL+LEFTCTRL
|
219
242
|
YAML
|
220
243
|
|
221
|
-
|
244
|
+
keybinds = DEFAULT_EMERGENCY_KEYBIND.split("+")
|
222
245
|
end
|
223
246
|
|
224
247
|
MultiLogger.info "Emergency ungrab keybind: #{keybinds[0]}+#{keybinds[1]}"
|
225
248
|
|
226
|
-
first_keycode =
|
227
|
-
second_keycode =
|
249
|
+
first_keycode = key_to_code(keybinds[0])
|
250
|
+
second_keycode = key_to_code(keybinds[1])
|
228
251
|
|
229
252
|
@emergency_stop = lambda do |prev, current|
|
230
253
|
if (prev&.code == first_keycode && prev.value != 0) && (current.code == second_keycode && current.value != 0)
|
@@ -246,48 +269,45 @@ module Fusuma
|
|
246
269
|
# @param [Integer] code
|
247
270
|
# @return [Integer, nil]
|
248
271
|
def find_remapped_code(mapping, code)
|
249
|
-
key =
|
272
|
+
key = code_to_key(code) # key = "A"
|
250
273
|
remapped_key = mapping.fetch(key.to_sym, nil) # remapped_key = "b"
|
251
274
|
return code unless remapped_key # return original code if key is not found
|
252
275
|
|
253
|
-
|
276
|
+
key_to_code(remapped_key) # remapped_code = 48
|
254
277
|
end
|
255
278
|
|
256
279
|
# Find key name from key code
|
257
280
|
# @example
|
258
|
-
#
|
259
|
-
#
|
281
|
+
# code_to_key(30) # => "A"
|
282
|
+
# code_to_key(48) # => "B"
|
283
|
+
# code_to_key(272) # => "BTN_LEFT"
|
260
284
|
# @param [Integer] code
|
261
285
|
# @return [String]
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
@keys_per_code[code]
|
286
|
+
# @return [nil] when key is not found
|
287
|
+
def code_to_key(code)
|
288
|
+
KEYMAP[code]
|
266
289
|
end
|
267
290
|
|
268
291
|
# Find key code from key name (e.g. "A", "B", "BTN_LEFT")
|
269
292
|
# If key name is not found, return nil
|
270
293
|
# @example
|
271
|
-
#
|
272
|
-
#
|
273
|
-
#
|
274
|
-
#
|
294
|
+
# key_to_code("A") # => 30
|
295
|
+
# key_to_code("B") # => 48
|
296
|
+
# key_to_code("BTN_LEFT") # => 272
|
297
|
+
# key_to_code("NOT_FOUND") # => nil
|
275
298
|
# @param [String] key
|
276
299
|
# @return [Integer] when key is available
|
277
300
|
# @return [nil] when key is not available
|
278
|
-
def
|
279
|
-
# { KEY_A => 30, KEY_B => 48, ... }
|
280
|
-
@codes_per_key ||= Revdev.constants.select { |c| c.start_with?("KEY_", "BTN_") }.map { |c| [c, Revdev.const_get(c)] }.to_h
|
281
|
-
|
301
|
+
def key_to_code(key)
|
282
302
|
case key
|
283
303
|
when String
|
284
304
|
if key.start_with?("BTN_")
|
285
|
-
|
305
|
+
CODEMAP[key.upcase.to_sym]
|
286
306
|
else
|
287
|
-
|
307
|
+
CODEMAP["KEY_#{key}".upcase.to_sym]
|
288
308
|
end
|
289
309
|
when Integer
|
290
|
-
|
310
|
+
CODEMAP["KEY_#{key}".upcase.to_sym]
|
291
311
|
end
|
292
312
|
end
|
293
313
|
|
@@ -303,7 +323,12 @@ module Fusuma
|
|
303
323
|
break true
|
304
324
|
else
|
305
325
|
# wait until all keys are released
|
306
|
-
|
326
|
+
begin
|
327
|
+
device.read_input_event
|
328
|
+
rescue Errno::ENODEV => e
|
329
|
+
MultiLogger.warn("Device removed while waiting to release keys: #{e.message}")
|
330
|
+
return false
|
331
|
+
end
|
307
332
|
end
|
308
333
|
end
|
309
334
|
end
|
@@ -18,7 +18,6 @@ module Fusuma
|
|
18
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
21
|
@palm_detectors = @source_touchpads.each_with_object({}) do |source_touchpad, palm_detectors|
|
23
22
|
palm_detectors[source_touchpad] = PalmDetection.new(source_touchpad)
|
24
23
|
end
|
@@ -34,6 +33,9 @@ module Fusuma
|
|
34
33
|
touch_state = {}
|
35
34
|
mt_slot = 0
|
36
35
|
finger_state = nil
|
36
|
+
|
37
|
+
prev_valid_touch = false
|
38
|
+
prev_status = nil
|
37
39
|
loop do
|
38
40
|
ios = IO.select(@source_touchpads.map(&:file)) # , @layer_manager.reader])
|
39
41
|
io = ios&.first&.first
|
@@ -131,10 +133,29 @@ module Fusuma
|
|
131
133
|
end
|
132
134
|
|
133
135
|
if syn_report
|
136
|
+
# Whether any slot is valid (touching)
|
137
|
+
valid_touch = touch_state.any? { |_, st| st[:valid_touch_point] }
|
138
|
+
|
139
|
+
status =
|
140
|
+
if valid_touch
|
141
|
+
prev_valid_touch ? "update" : "begin"
|
142
|
+
else
|
143
|
+
prev_valid_touch ? "end" : "cancelled"
|
144
|
+
end
|
145
|
+
|
146
|
+
if status == prev_status
|
147
|
+
next
|
148
|
+
end
|
149
|
+
|
134
150
|
# TODO: define format as fusuma_input
|
135
151
|
# TODO: Add data to identify multiple touchpads
|
136
|
-
data = {
|
152
|
+
data = {
|
153
|
+
finger: finger_state,
|
154
|
+
status: status
|
155
|
+
}
|
137
156
|
@fusuma_writer.write(data.to_msgpack)
|
157
|
+
prev_status = status
|
158
|
+
prev_valid_touch = valid_touch
|
138
159
|
end
|
139
160
|
end
|
140
161
|
rescue => e
|
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.11.1
|
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-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fusuma
|