fusuma-plugin-sendkey 0.11.1 → 0.13.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: 840d73a0df9fce8d9c314fa2834e209e7f6387a2c2acd1b56787c67b885ff361
4
- data.tar.gz: eb761d6506cad7089f4c019550332056e073861050fb01e0a11904a50f550e7b
3
+ metadata.gz: c611a6d5d766d2e57a3c413e3c06b83561f20d9768d785601c0a3395128c77f9
4
+ data.tar.gz: 5ddd9dc6449c2db16e3e4de26e08ed4334c2e9b274f81ba4bdfa1301815bfb44
5
5
  SHA512:
6
- metadata.gz: c33165835115544860593abc6d41ba24084712d7b4fcb10f4dc5efd27dcf6fc5dffb0ce78fcee1182a616539ba059b816e8125e56d4fd27365b58a1e810b152d
7
- data.tar.gz: 95c2123025840a37dc4bb35bf95c0a848b1172dfa7a89fadff0fb92592cd9d44f66d283aa5061f943a3e1f9eaf8575256f164d6179e16d561607fa615bea69fe
6
+ metadata.gz: 118858d9a59878f2e830e444577be1b543ceac410027e3be5e564385d19876f0d5aa4a21f55935fede4cbc18f613e99cc8489b0c4128c1dc5d5d4d8b4e65ad0f
7
+ data.tar.gz: 28bbb84b4aaa9a5903d6473bffd5139bd2fe8ab942cbbbfc99a47e5a2567a6c76f737eb4e84ed917807f554c868f0e7c52f9d4d1bfd340694bbcfbdca4b5358b
data/exe/fusuma-sendkey CHANGED
@@ -1,34 +1,32 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'optparse'
5
- require 'fusuma/config'
6
- require 'fusuma/plugin/inputs/libinput_command_input.rb'
7
- require_relative '../lib/fusuma/plugin/sendkey/keyboard.rb'
8
- require_relative '../lib/fusuma/plugin/sendkey/version.rb'
4
+ require "optparse"
5
+ require "fusuma/config"
6
+ require "fusuma/plugin/executors/executor"
7
+ require "fusuma/plugin/inputs/libinput_command_input"
8
+ require_relative "../lib/fusuma/plugin/sendkey/keyboard"
9
+ require_relative "../lib/fusuma/plugin/executors/sendkey_executor"
10
+ require_relative "../lib/fusuma/plugin/sendkey/version"
9
11
 
10
12
  option = {}
11
13
  opt = OptionParser.new
12
14
 
13
- opt.on('-l', '--list-keycodes',
14
- 'List available keycodes') do |v|
15
+ opt.on("-l", "--list-keycodes",
16
+ "List available keycodes") do |v|
15
17
  option[:list] = v
16
18
  end
17
19
 
18
- opt.on('--version', 'Show version') do |v|
20
+ opt.on("--version", "Show version") do |v|
19
21
  option[:version] = v
20
22
  end
21
23
 
22
- opt.parse!(ARGV)
23
-
24
- device_name = Fusuma::Config.instance.fetch_config_params(
25
- :device_name,
26
- Fusuma::Config::Index.new([:plugin, :executors, :sendkey_executor])
27
- ).fetch(:device_name, 'keyboard|Keyboard|KEYBOARD')
28
-
29
- if option[:list]
30
- puts Fusuma::Plugin::Sendkey::Keyboard.new(name_pattern: device_name).search_codes
31
- return
24
+ begin
25
+ opt.parse!(ARGV)
26
+ rescue OptionParser::InvalidOption => e
27
+ warn e
28
+ warn opt.help
29
+ exit 1
32
30
  end
33
31
 
34
32
  if option[:version]
@@ -36,20 +34,29 @@ if option[:version]
36
34
  return
37
35
  end
38
36
 
37
+ executor_index = Fusuma::Config::Index.new([:plugin, :executors, :sendkey_executor])
38
+ name_patterns = Fusuma::Config.instance.fetch_config_params(:device_name, executor_index).fetch(:device_name)
39
+
40
+ device = Fusuma::Plugin::Sendkey::Keyboard.find_device(name_patterns: name_patterns)
41
+ keyboard = Fusuma::Plugin::Sendkey::Keyboard.new(device: device)
42
+ if option[:list]
43
+ puts keyboard.search_codes("KEY_").map { |sym| sym.to_s.delete_prefix("KEY_") }
44
+ puts keyboard.search_codes("BTN_")
45
+ return
46
+ end
47
+
39
48
  args = ARGV.first
40
49
 
41
50
  if args.nil?
42
- warn 'fusuma-sendkey require 1 arugument'
43
- warn 'e.g. fusuma-sendkey LEFTALT+LEFT'
44
- warn 'e.g. fusuma-sendkey [A, B, C]'
51
+ warn "fusuma-sendkey require 1 arugument"
52
+ warn "e.g. fusuma-sendkey LEFTALT+LEFT"
53
+ warn "e.g. fusuma-sendkey [A, B, C]"
45
54
  exit 1
46
55
  end
47
56
 
48
-
49
57
  # remove [ and ] from args
50
- params = args.delete('[]').split(',').map(&:strip)
58
+ params = args.delete("[]").split(",").map(&:strip)
51
59
 
52
- keyboard = Fusuma::Plugin::Sendkey::Keyboard.new(name_pattern: device_name)
53
60
  return unless keyboard.valid?(params)
54
61
 
55
62
  if params.size == 1
@@ -18,7 +18,7 @@ module Fusuma
18
18
 
19
19
  def config_param_types
20
20
  {
21
- device_name: String
21
+ device_name: [String, Array]
22
22
  }
23
23
  end
24
24
 
@@ -55,7 +55,10 @@ module Fusuma
55
55
  private
56
56
 
57
57
  def keyboard
58
- @keyboard ||= Sendkey::Keyboard.new(name_pattern: @device_name)
58
+ @keyboard ||= begin
59
+ device = Sendkey::Keyboard.find_device(name_patterns: @device_name)
60
+ Sendkey::Keyboard.new(device: device)
61
+ end
59
62
  end
60
63
 
61
64
  def search_param(event)
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "revdev"
4
+ require "set"
5
+
3
6
  module Fusuma
4
7
  module Plugin
5
8
  module Sendkey
@@ -7,8 +10,11 @@ module Fusuma
7
10
  class Device
8
11
  def initialize(path:)
9
12
  @evdev = Revdev::EventDevice.new(path)
13
+ @capabilities = Set.new
10
14
  end
11
15
 
16
+ attr_reader :capabilities
17
+
12
18
  def path
13
19
  raise "Device path is not found" if @evdev.nil?
14
20
 
@@ -18,6 +24,31 @@ module Fusuma
18
24
  def write_event(event)
19
25
  @evdev.write_input_event(event)
20
26
  end
27
+
28
+ def reload_capability
29
+ @capabilities.clear
30
+
31
+ buf = fetch_capabilities
32
+ buf.unpack("C*").each_with_index do |byte, i|
33
+ 8.times do |bit| # 0..7
34
+ if byte[bit] != 0
35
+ @capabilities << (i * 8 + bit)
36
+ end
37
+ end
38
+ end
39
+ @capabilities
40
+ end
41
+
42
+ private
43
+
44
+ EVIOCGBIT = 2153792801
45
+
46
+ def fetch_capabilities
47
+ file = File.open(path, "r")
48
+ buf = +"" # unfreeze string
49
+ file.ioctl(EVIOCGBIT, buf)
50
+ buf
51
+ end
21
52
  end
22
53
  end
23
54
  end
@@ -10,7 +10,7 @@ module Fusuma
10
10
  module Sendkey
11
11
  # Emulate Keyboard
12
12
  class Keyboard
13
- INTERVAL = 0.01
13
+ INTERVAL = 0.03
14
14
 
15
15
  MODIFIER_KEY_CODES = %w[
16
16
  KEY_CAPSLOCK
@@ -24,25 +24,28 @@ module Fusuma
24
24
  KEY_RIGHTMETA
25
25
  ].freeze
26
26
 
27
- def self.find_device(name_pattern:)
27
+ def self.find_device(name_patterns:)
28
28
  Fusuma::Device.reset
29
- Fusuma::Device.all.find { |d|
30
- next unless /keyboard/.match?(d.capabilities)
31
29
 
32
- d.name.match(/#{name_pattern}/)
33
- }
34
- end
30
+ Array(name_patterns).each do |name_pattern|
31
+ fusuma_device = Fusuma::Device.all.find { |d|
32
+ next unless d.capabilities.include?("keyboard")
35
33
 
36
- def initialize(name_pattern: nil)
37
- device = Keyboard.find_device(name_pattern: name_pattern)
34
+ d.name.match(/#{name_pattern}/)
35
+ }
38
36
 
39
- if device.nil?
37
+ if fusuma_device
38
+ MultiLogger.info "sendkey: Keyboard: #{fusuma_device.name}"
39
+ return Device.new(path: "/dev/input/#{fusuma_device.id}")
40
+ end
40
41
  warn "sendkey: Keyboard: /#{name_pattern}/ is not found"
41
- exit(1)
42
42
  end
43
- MultiLogger.info "sendkey: Keyboard: #{device.name}"
44
43
 
45
- @device = Device.new(path: "/dev/input/#{device.id}")
44
+ exit(1)
45
+ end
46
+
47
+ def initialize(device:)
48
+ @device = device
46
49
  end
47
50
 
48
51
  # @param params [Array]
@@ -65,8 +68,8 @@ module Fusuma
65
68
  def type(param:, keep: "", clear: :none)
66
69
  return unless param.is_a?(String)
67
70
 
68
- param_keycodes = param_to_keycodes(param)
69
- type_keycodes = param_keycodes - param_to_keycodes(keep)
71
+ param_keycodes = param_to_codes(param)
72
+ type_keycodes = param_keycodes - param_to_codes(keep)
70
73
 
71
74
  clear_keycodes =
72
75
  case clear
@@ -76,12 +79,13 @@ module Fusuma
76
79
  []
77
80
  else
78
81
  # release keys specified by clearmodifiers
79
- param_to_keycodes(clear)
82
+ param_to_codes(clear)
80
83
  end
81
84
 
82
85
  clear_modifiers(clear_keycodes - param_keycodes)
83
86
 
84
87
  type_keycodes.each { |keycode| keydown(keycode) && key_sync }
88
+ sleep(INTERVAL)
85
89
  type_keycodes.reverse_each { |keycode| keyup(keycode) && key_sync }
86
90
  end
87
91
 
@@ -100,7 +104,7 @@ module Fusuma
100
104
  params.all? { |param| valid?(param) }
101
105
  when String
102
106
  param = params
103
- keycodes = param_to_keycodes(param)
107
+ keycodes = param_to_codes(param)
104
108
  keycodes.all? { |keycode| support?(keycode) }
105
109
  else
106
110
  MultiLogger.error "sendkey: Invalid config: #{params}"
@@ -126,35 +130,40 @@ module Fusuma
126
130
  0
127
131
  )
128
132
  @device.write_event(event)
129
- sleep(INTERVAL)
130
133
  end
131
134
 
132
- def support?(keycode)
133
- @supported_code ||= {}
134
- @supported_code[keycode] ||= find_code(keycode: keycode)
135
+ def capabilities
136
+ return @capabilities if defined?(@capabilities)
137
+
138
+ @capabilities = Set.new.tap do |set|
139
+ @device.reload_capability.each do |id|
140
+ code_sym = Revdev::REVERSE_MAPS[:KEY][id]
141
+ set << code_sym if code_sym
142
+ end
143
+ end
135
144
  end
136
145
 
137
- def warn_undefined_codes(keycode:)
138
- query = keycode&.upcase&.gsub("KEY_", "")
146
+ def support?(code)
147
+ @supported_code ||= {}
148
+ @supported_code[code] ||= find_code(code)
149
+ end
139
150
 
140
- candidates = search_codes(query: query)
151
+ def warn_undefined_codes(code)
152
+ candidates = search_codes(code).map { |c| remove_prefix(c.to_s) }
141
153
 
142
154
  warn "Did you mean? #{candidates.join(" / ")}" unless candidates.empty?
143
- warn "sendkey: #{remove_prefix(keycode)} is unsupported."
144
- end
145
155
 
146
- def search_codes(query: nil)
147
- Revdev.constants
148
- .select { |c| c[/KEY_.*#{query}.*/] }
149
- .map { |c| c.to_s.gsub("KEY_", "") }
156
+ warn "sendkey: #{remove_prefix(code)} is unsupported."
150
157
  end
151
158
 
152
- def find_code(keycode: nil)
153
- query = keycode&.upcase&.gsub("KEY_", "")
159
+ def search_codes(code)
160
+ capabilities.select { |c| c[code] }
161
+ end
154
162
 
155
- result = Revdev.constants.find { |c| c == "KEY_#{query}".to_sym }
163
+ def find_code(code)
164
+ result = capabilities.find { |c| c == code.to_sym }
156
165
 
157
- warn_undefined_codes(keycode: keycode) unless result
166
+ warn_undefined_codes(code) unless result
158
167
  result
159
168
  end
160
169
 
@@ -169,14 +178,19 @@ module Fusuma
169
178
 
170
179
  # @param [String]
171
180
  # @return [Array<String>]
172
- def param_to_keycodes(param)
173
- param.split("+").map { |keyname| add_key_prefix(keyname) }
181
+ def param_to_codes(param)
182
+ param.split("+").map { |keyname| add_prefix(keyname) }
174
183
  end
175
184
 
176
185
  private
177
186
 
178
- def add_key_prefix(code)
179
- "KEY_#{code.upcase}"
187
+ def add_prefix(code)
188
+ code.upcase!
189
+ if code.start_with?("BTN_")
190
+ code
191
+ else
192
+ "KEY_#{code}"
193
+ end
180
194
  end
181
195
 
182
196
  def remove_prefix(keycode)
@@ -3,7 +3,7 @@
3
3
  module Fusuma
4
4
  module Plugin
5
5
  module Sendkey
6
- VERSION = "0.11.1"
6
+ VERSION = "0.13.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-sendkey
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.1
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - iberianpig
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-09-13 00:00:00.000000000 Z
11
+ date: 2024-09-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fusuma