fusuma-plugin-remap 0.11.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: b55e5ef616cbf48bc0a8c3a4c0b9b91dbed01c3b4dc87f53f09fa51ab6c34227
4
- data.tar.gz: 1e34c8882e52d3191092576ab5d056d74c1ea0d130963a37304ce2a8bc6b0fdf
3
+ metadata.gz: c1a6f601df78486fb3bf89f9c7902fe9fd46e45c33e2807eff9f0c4b5a38ec45
4
+ data.tar.gz: 50ca1d1da716e62d9ed9cc3973b201f9b8c93b00b5e313559bc5d7d4a73bfd3d
5
5
  SHA512:
6
- metadata.gz: bb30877c6629814e6aff80127aa63045e4901d416a568d1a6f0e7f268254509903df5df8d90382a7d739ea3b2a6b666a461f57d9af0ce00941152d2296953efd
7
- data.tar.gz: f11178d8bf7c553a1568b67e1a62b4cb747d51c0b67008330b98b17228b82a5d41cecd5b4de2f259d2d572f539e4f55daaa75f79fdd7c3a2608ac4013a2473f7
6
+ metadata.gz: 881a29098c368a60f0d4469d77b1ffc118d0c9eb2df02d2b7c492ba356f30ab0ad740a73bfa96e229a1fd16d46a7a839139c7b4077e26fb30b092d0c142ca28c
7
+ data.tar.gz: 50dd4b8c9554ee17e338a5ded7248d1b4f9215d03ca5d19d5e2c8d97731687b42b1edb2105d7ebf7539ac2718bb3d3085db4c800db26cad54426be93fe854643
@@ -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 = find_key_from_code(input_event.code)
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
- @fusuma_writer.write(data.to_msgpack)
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
- remapped_event = InputEvent.new(nil, input_event.type, find_code_from_key(remapped), input_event.value)
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.error "Invalid emergency ungrab keybinds: #{keybinds}"
213
- MultiLogger.error "Please set two keys separated by '+'"
214
- MultiLogger.error <<~YAML
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
- exit 1
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 = find_code_from_key(keybinds[0])
227
- second_keycode = find_code_from_key(keybinds[1])
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 = find_key_from_code(code) # key = "A"
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
- find_code_from_key(remapped_key) # remapped_code = 48
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
- # find_key_from_code(30) # => "A"
259
- # find_key_from_code(48) # => "B"
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
- def find_key_from_code(code)
263
- # { 30 => :A, 48 => :B, ... }
264
- @keys_per_code ||= Revdev.constants.select { |c| c.start_with? "KEY_" }.map { |c| [Revdev.const_get(c), c.to_s.delete_prefix("KEY_")] }.to_h
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
- # find_code_from_key("A") # => 30
272
- # find_code_from_key("B") # => 48
273
- # find_code_from_key("BTN_LEFT") # => 272
274
- # find_code_from_key("NOT_FOUND") # => nil
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 find_code_from_key(key)
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
- @codes_per_key[key.upcase.to_sym]
305
+ CODEMAP[key.upcase.to_sym]
286
306
  else
287
- @codes_per_key["KEY_#{key}".upcase.to_sym]
307
+ CODEMAP["KEY_#{key}".upcase.to_sym]
288
308
  end
289
309
  when Integer
290
- @codes_per_key["KEY_#{key}".upcase.to_sym]
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
- device.read_input_event
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
@@ -3,7 +3,7 @@
3
3
  module Fusuma
4
4
  module Plugin
5
5
  module Remap
6
- VERSION = "0.11.0"
6
+ VERSION = "0.11.1"
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.11.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-05-26 00:00:00.000000000 Z
11
+ date: 2025-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fusuma