fusuma-plugin-sendkey 0.12.0 → 0.13.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: 99275a36f4c77826f0b915f809aa8cca0dc52f1689c4f1e0226ba3f816ca2d06
4
- data.tar.gz: cd5f7f8a2d78b4226610ff32d8468300b6ff3fda010b11016779400330433503
3
+ metadata.gz: 65cd0d7ac4a2a78edf9e316d12e1a013a534817fb672228811d2a53deadb6d48
4
+ data.tar.gz: 7fac8215b62b4cfd7f7e83eaa2005864b94b56f295042ef610c0bca525752d5d
5
5
  SHA512:
6
- metadata.gz: 99f4727c128b6131e9ede5ef8e12fd2a9cb6de74c1b97a23290ea29c505465527d16b87b5adda35b429790883c95f404b6b3c73f96298d1e5309afb9a429e222
7
- data.tar.gz: 163a0a224c8ef964874f6fd9ac7c2acd2b55489e2773777a3da3b4e33994427b403525452b9ddf4778b4aad20b1a5d11cc3b9f3d3bf9c3abf1c5bb74fae0c630
6
+ metadata.gz: a6a6d245843e9e9bc4549e15290d3c64d01c19362b5da5892db2df79a807c3fde7a1d31ced8a0c1bf57dccaefa66aa962a5bc64fcf4198c429375c4cf3565a4c
7
+ data.tar.gz: e2bc2a7f42436038b2da1c68c72ad585375fa633c6d41396144815f101be42fe972899a5b0a0033d721124d63f680611f77b147ed54bad6ee60e866e3255a2fc
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)
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
@@ -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
+ KEY_INTERVAL = 0.03
14
14
 
15
15
  MODIFIER_KEY_CODES = %w[
16
16
  KEY_CAPSLOCK
@@ -24,30 +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
35
-
36
- def initialize(name_pattern: nil)
37
- device = nil
30
+ Array(name_patterns).each do |name_pattern|
31
+ fusuma_device = Fusuma::Device.all.find { |d|
32
+ next unless d.capabilities.include?("keyboard")
38
33
 
39
- Array(name_pattern).each do |pattern|
40
- device = Keyboard.find_device(name_pattern: pattern)
41
- break if device
42
- end
34
+ d.name.match(/#{name_pattern}/)
35
+ }
43
36
 
44
- 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
45
41
  warn "sendkey: Keyboard: /#{name_pattern}/ is not found"
46
- exit(1)
47
42
  end
48
- MultiLogger.info "sendkey: Keyboard: #{device.name}"
49
43
 
50
- @device = Device.new(path: "/dev/input/#{device.id}")
44
+ exit(1)
45
+ end
46
+
47
+ def initialize(device:)
48
+ @device = device
51
49
  end
52
50
 
53
51
  # @param params [Array]
@@ -70,8 +68,8 @@ module Fusuma
70
68
  def type(param:, keep: "", clear: :none)
71
69
  return unless param.is_a?(String)
72
70
 
73
- param_keycodes = param_to_keycodes(param)
74
- type_keycodes = param_keycodes - param_to_keycodes(keep)
71
+ param_keycodes = param_to_codes(param)
72
+ type_keycodes = param_keycodes - param_to_codes(keep)
75
73
 
76
74
  clear_keycodes =
77
75
  case clear
@@ -81,13 +79,13 @@ module Fusuma
81
79
  []
82
80
  else
83
81
  # release keys specified by clearmodifiers
84
- param_to_keycodes(clear)
82
+ param_to_codes(clear)
85
83
  end
86
84
 
87
85
  clear_modifiers(clear_keycodes - param_keycodes)
88
86
 
89
- type_keycodes.each { |keycode| keydown(keycode) && key_sync }
90
- type_keycodes.reverse_each { |keycode| keyup(keycode) && key_sync }
87
+ type_keycodes.each { |keycode| keydown(keycode) && key_sync && sleep(KEY_INTERVAL) }
88
+ type_keycodes.reverse_each { |keycode| keyup(keycode) && key_sync && sleep(KEY_INTERVAL) }
91
89
  end
92
90
 
93
91
  def keydown(keycode)
@@ -105,7 +103,7 @@ module Fusuma
105
103
  params.all? { |param| valid?(param) }
106
104
  when String
107
105
  param = params
108
- keycodes = param_to_keycodes(param)
106
+ keycodes = param_to_codes(param)
109
107
  keycodes.all? { |keycode| support?(keycode) }
110
108
  else
111
109
  MultiLogger.error "sendkey: Invalid config: #{params}"
@@ -131,35 +129,40 @@ module Fusuma
131
129
  0
132
130
  )
133
131
  @device.write_event(event)
134
- sleep(INTERVAL)
135
132
  end
136
133
 
137
- def support?(keycode)
138
- @supported_code ||= {}
139
- @supported_code[keycode] ||= find_code(keycode: keycode)
134
+ def capabilities
135
+ return @capabilities if defined?(@capabilities)
136
+
137
+ @capabilities = Set.new.tap do |set|
138
+ @device.reload_capability.each do |id|
139
+ code_sym = Revdev::REVERSE_MAPS[:KEY][id]
140
+ set << code_sym if code_sym
141
+ end
142
+ end
140
143
  end
141
144
 
142
- def warn_undefined_codes(keycode:)
143
- query = keycode&.upcase&.gsub("KEY_", "")
145
+ def support?(code)
146
+ @supported_code ||= {}
147
+ @supported_code[code] ||= find_code(code)
148
+ end
144
149
 
145
- candidates = search_codes(query: query)
150
+ def warn_undefined_codes(code)
151
+ candidates = search_codes(code).map { |c| remove_prefix(c.to_s) }
146
152
 
147
153
  warn "Did you mean? #{candidates.join(" / ")}" unless candidates.empty?
148
- warn "sendkey: #{remove_prefix(keycode)} is unsupported."
149
- end
150
154
 
151
- def search_codes(query: nil)
152
- Revdev.constants
153
- .select { |c| c[/KEY_.*#{query}.*/] }
154
- .map { |c| c.to_s.gsub("KEY_", "") }
155
+ warn "sendkey: #{remove_prefix(code)} is unsupported."
155
156
  end
156
157
 
157
- def find_code(keycode: nil)
158
- query = keycode&.upcase&.gsub("KEY_", "")
158
+ def search_codes(code)
159
+ capabilities.select { |c| c[code] }
160
+ end
159
161
 
160
- result = Revdev.constants.find { |c| c == "KEY_#{query}".to_sym }
162
+ def find_code(code)
163
+ result = capabilities.find { |c| c == code.to_sym }
161
164
 
162
- warn_undefined_codes(keycode: keycode) unless result
165
+ warn_undefined_codes(code) unless result
163
166
  result
164
167
  end
165
168
 
@@ -174,14 +177,19 @@ module Fusuma
174
177
 
175
178
  # @param [String]
176
179
  # @return [Array<String>]
177
- def param_to_keycodes(param)
178
- param.split("+").map { |keyname| add_key_prefix(keyname) }
180
+ def param_to_codes(param)
181
+ param.split("+").map { |keyname| add_prefix(keyname) }
179
182
  end
180
183
 
181
184
  private
182
185
 
183
- def add_key_prefix(code)
184
- "KEY_#{code.upcase}"
186
+ def add_prefix(code)
187
+ code.upcase!
188
+ if code.start_with?("BTN_")
189
+ code
190
+ else
191
+ "KEY_#{code}"
192
+ end
185
193
  end
186
194
 
187
195
  def remove_prefix(keycode)
@@ -3,7 +3,7 @@
3
3
  module Fusuma
4
4
  module Plugin
5
5
  module Sendkey
6
- VERSION = "0.12.0"
6
+ VERSION = "0.13.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-sendkey
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.13.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - iberianpig
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-09-21 00:00:00.000000000 Z
11
+ date: 2024-10-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fusuma
@@ -62,7 +62,7 @@ homepage: https://github.com/iberianpig/fusuma-plugin-sendkey
62
62
  licenses:
63
63
  - MIT
64
64
  metadata: {}
65
- post_install_message:
65
+ post_install_message:
66
66
  rdoc_options: []
67
67
  require_paths:
68
68
  - lib
@@ -78,7 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
78
  version: '0'
79
79
  requirements: []
80
80
  rubygems_version: 3.4.19
81
- signing_key:
81
+ signing_key:
82
82
  specification_version: 4
83
83
  summary: Fusuma plugin to send keyboard events
84
84
  test_files: []