lib/fusuma/plugin/sendkey/keyboard.rb in fusuma-plugin-sendkey-0.12.0 vs lib/fusuma/plugin/sendkey/keyboard.rb in fusuma-plugin-sendkey-0.13.0
- old
+ new
@@ -8,11 +8,11 @@
module Fusuma
module Plugin
module Sendkey
# Emulate Keyboard
class Keyboard
- INTERVAL = 0.01
+ INTERVAL = 0.03
MODIFIER_KEY_CODES = %w[
KEY_CAPSLOCK
KEY_LEFTALT
KEY_LEFTCTRL
@@ -22,36 +22,34 @@
KEY_RIGHTCTRL
KEY_RIGHTSHIFT
KEY_RIGHTMETA
].freeze
- def self.find_device(name_pattern:)
+ def self.find_device(name_patterns:)
Fusuma::Device.reset
- Fusuma::Device.all.find { |d|
- next unless /keyboard/.match?(d.capabilities)
- d.name.match(/#{name_pattern}/)
- }
- end
+ Array(name_patterns).each do |name_pattern|
+ fusuma_device = Fusuma::Device.all.find { |d|
+ next unless d.capabilities.include?("keyboard")
- def initialize(name_pattern: nil)
- device = nil
+ d.name.match(/#{name_pattern}/)
+ }
- Array(name_pattern).each do |pattern|
- device = Keyboard.find_device(name_pattern: pattern)
- break if device
- end
-
- if device.nil?
+ if fusuma_device
+ MultiLogger.info "sendkey: Keyboard: #{fusuma_device.name}"
+ return Device.new(path: "/dev/input/#{fusuma_device.id}")
+ end
warn "sendkey: Keyboard: /#{name_pattern}/ is not found"
- exit(1)
end
- MultiLogger.info "sendkey: Keyboard: #{device.name}"
- @device = Device.new(path: "/dev/input/#{device.id}")
+ exit(1)
end
+ def initialize(device:)
+ @device = device
+ end
+
# @param params [Array]
def types(args)
return unless args.is_a?(Array)
args.each do |arg|
@@ -68,27 +66,28 @@
# @param keep [String] key names separated by '+' to keep
# @param clear [String, Symbol, TrueClass] key names separated by '+' to clear or :all to release all modifiers
def type(param:, keep: "", clear: :none)
return unless param.is_a?(String)
- param_keycodes = param_to_keycodes(param)
- type_keycodes = param_keycodes - param_to_keycodes(keep)
+ param_keycodes = param_to_codes(param)
+ type_keycodes = param_keycodes - param_to_codes(keep)
clear_keycodes =
case clear
when true
MODIFIER_KEY_CODES
when :none, false
[]
else
# release keys specified by clearmodifiers
- param_to_keycodes(clear)
+ param_to_codes(clear)
end
clear_modifiers(clear_keycodes - param_keycodes)
type_keycodes.each { |keycode| keydown(keycode) && key_sync }
+ sleep(INTERVAL)
type_keycodes.reverse_each { |keycode| keyup(keycode) && key_sync }
end
def keydown(keycode)
send_event(code: keycode, press: true)
@@ -103,11 +102,11 @@
case params
when Array
params.all? { |param| valid?(param) }
when String
param = params
- keycodes = param_to_keycodes(param)
+ keycodes = param_to_codes(param)
keycodes.all? { |keycode| support?(keycode) }
else
MultiLogger.error "sendkey: Invalid config: #{params}"
nil
end
@@ -129,39 +128,44 @@
Revdev.const_get(:EV_SYN),
Revdev.const_get(:SYN_REPORT),
0
)
@device.write_event(event)
- sleep(INTERVAL)
end
- def support?(keycode)
+ def capabilities
+ return @capabilities if defined?(@capabilities)
+
+ @capabilities = Set.new.tap do |set|
+ @device.reload_capability.each do |id|
+ code_sym = Revdev::REVERSE_MAPS[:KEY][id]
+ set << code_sym if code_sym
+ end
+ end
+ end
+
+ def support?(code)
@supported_code ||= {}
- @supported_code[keycode] ||= find_code(keycode: keycode)
+ @supported_code[code] ||= find_code(code)
end
- def warn_undefined_codes(keycode:)
- query = keycode&.upcase&.gsub("KEY_", "")
+ def warn_undefined_codes(code)
+ candidates = search_codes(code).map { |c| remove_prefix(c.to_s) }
- candidates = search_codes(query: query)
-
warn "Did you mean? #{candidates.join(" / ")}" unless candidates.empty?
- warn "sendkey: #{remove_prefix(keycode)} is unsupported."
+
+ warn "sendkey: #{remove_prefix(code)} is unsupported."
end
- def search_codes(query: nil)
- Revdev.constants
- .select { |c| c[/KEY_.*#{query}.*/] }
- .map { |c| c.to_s.gsub("KEY_", "") }
+ def search_codes(code)
+ capabilities.select { |c| c[code] }
end
- def find_code(keycode: nil)
- query = keycode&.upcase&.gsub("KEY_", "")
+ def find_code(code)
+ result = capabilities.find { |c| c == code.to_sym }
- result = Revdev.constants.find { |c| c == "KEY_#{query}".to_sym }
-
- warn_undefined_codes(keycode: keycode) unless result
+ warn_undefined_codes(code) unless result
result
end
def keycode_const(keycode)
Object.const_get "Revdev::#{keycode}"
@@ -172,17 +176,22 @@
keycodes.each { |code| send_event(code: code, press: false) }
end
# @param [String]
# @return [Array<String>]
- def param_to_keycodes(param)
- param.split("+").map { |keyname| add_key_prefix(keyname) }
+ def param_to_codes(param)
+ param.split("+").map { |keyname| add_prefix(keyname) }
end
private
- def add_key_prefix(code)
- "KEY_#{code.upcase}"
+ def add_prefix(code)
+ code.upcase!
+ if code.start_with?("BTN_")
+ code
+ else
+ "KEY_#{code}"
+ end
end
def remove_prefix(keycode)
keycode.gsub("KEY_", "")
end