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