fusuma-plugin-sendkey 0.12.0 → 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: 99275a36f4c77826f0b915f809aa8cca0dc52f1689c4f1e0226ba3f816ca2d06
4
- data.tar.gz: cd5f7f8a2d78b4226610ff32d8468300b6ff3fda010b11016779400330433503
3
+ metadata.gz: c611a6d5d766d2e57a3c413e3c06b83561f20d9768d785601c0a3395128c77f9
4
+ data.tar.gz: 5ddd9dc6449c2db16e3e4de26e08ed4334c2e9b274f81ba4bdfa1301815bfb44
5
5
  SHA512:
6
- metadata.gz: 99f4727c128b6131e9ede5ef8e12fd2a9cb6de74c1b97a23290ea29c505465527d16b87b5adda35b429790883c95f404b6b3c73f96298d1e5309afb9a429e222
7
- data.tar.gz: 163a0a224c8ef964874f6fd9ac7c2acd2b55489e2773777a3da3b4e33994427b403525452b9ddf4778b4aad20b1a5d11cc3b9f3d3bf9c3abf1c5bb74fae0c630
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)
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
+ 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,12 +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
87
  type_keycodes.each { |keycode| keydown(keycode) && key_sync }
88
+ sleep(INTERVAL)
90
89
  type_keycodes.reverse_each { |keycode| keyup(keycode) && key_sync }
91
90
  end
92
91
 
@@ -105,7 +104,7 @@ module Fusuma
105
104
  params.all? { |param| valid?(param) }
106
105
  when String
107
106
  param = params
108
- keycodes = param_to_keycodes(param)
107
+ keycodes = param_to_codes(param)
109
108
  keycodes.all? { |keycode| support?(keycode) }
110
109
  else
111
110
  MultiLogger.error "sendkey: Invalid config: #{params}"
@@ -131,35 +130,40 @@ module Fusuma
131
130
  0
132
131
  )
133
132
  @device.write_event(event)
134
- sleep(INTERVAL)
135
133
  end
136
134
 
137
- def support?(keycode)
138
- @supported_code ||= {}
139
- @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
140
144
  end
141
145
 
142
- def warn_undefined_codes(keycode:)
143
- query = keycode&.upcase&.gsub("KEY_", "")
146
+ def support?(code)
147
+ @supported_code ||= {}
148
+ @supported_code[code] ||= find_code(code)
149
+ end
144
150
 
145
- candidates = search_codes(query: query)
151
+ def warn_undefined_codes(code)
152
+ candidates = search_codes(code).map { |c| remove_prefix(c.to_s) }
146
153
 
147
154
  warn "Did you mean? #{candidates.join(" / ")}" unless candidates.empty?
148
- warn "sendkey: #{remove_prefix(keycode)} is unsupported."
149
- end
150
155
 
151
- def search_codes(query: nil)
152
- Revdev.constants
153
- .select { |c| c[/KEY_.*#{query}.*/] }
154
- .map { |c| c.to_s.gsub("KEY_", "") }
156
+ warn "sendkey: #{remove_prefix(code)} is unsupported."
155
157
  end
156
158
 
157
- def find_code(keycode: nil)
158
- query = keycode&.upcase&.gsub("KEY_", "")
159
+ def search_codes(code)
160
+ capabilities.select { |c| c[code] }
161
+ end
159
162
 
160
- result = Revdev.constants.find { |c| c == "KEY_#{query}".to_sym }
163
+ def find_code(code)
164
+ result = capabilities.find { |c| c == code.to_sym }
161
165
 
162
- warn_undefined_codes(keycode: keycode) unless result
166
+ warn_undefined_codes(code) unless result
163
167
  result
164
168
  end
165
169
 
@@ -174,14 +178,19 @@ module Fusuma
174
178
 
175
179
  # @param [String]
176
180
  # @return [Array<String>]
177
- def param_to_keycodes(param)
178
- param.split("+").map { |keyname| add_key_prefix(keyname) }
181
+ def param_to_codes(param)
182
+ param.split("+").map { |keyname| add_prefix(keyname) }
179
183
  end
180
184
 
181
185
  private
182
186
 
183
- def add_key_prefix(code)
184
- "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
185
194
  end
186
195
 
187
196
  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.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.12.0
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-21 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