Class: Fusuma::Plugin::Sendkey::Keyboard
- Inherits:
-
Object
- Object
- Fusuma::Plugin::Sendkey::Keyboard
- Defined in:
- lib/fusuma/plugin/sendkey/keyboard.rb
Overview
Emulate Keyboard
Constant Summary collapse
- KEY_INTERVAL =
0.03
- MODIFIER_KEY_CODES =
%w[ KEY_CAPSLOCK KEY_LEFTALT KEY_LEFTCTRL KEY_LEFTMETA KEY_LEFTSHIFT KEY_RIGHTALT KEY_RIGHTCTRL KEY_RIGHTSHIFT KEY_RIGHTMETA ].freeze
Class Method Summary collapse
Instance Method Summary collapse
- #capabilities ⇒ Object
- #clear_modifiers(keycodes) ⇒ Object
- #find_code(code) ⇒ Object
-
#initialize(device:) ⇒ Keyboard
constructor
A new instance of Keyboard.
- #key_sync ⇒ Object
- #keycode_const(keycode) ⇒ Object
- #keydown(keycode) ⇒ Object
- #keyup(keycode) ⇒ Object
- #param_to_codes(param) ⇒ Array<String>
- #search_codes(code) ⇒ Object
- #send_event(code:, press: true) ⇒ Object
- #support?(code) ⇒ Boolean
- #type(param:, keep: "", clear: :none) ⇒ Object
- #types(args) ⇒ Object
- #valid?(params) ⇒ TrueClass, FalseClass
- #warn_undefined_codes(code) ⇒ Object
Constructor Details
#initialize(device:) ⇒ Keyboard
Returns a new instance of Keyboard.
47 48 49 |
# File 'lib/fusuma/plugin/sendkey/keyboard.rb', line 47 def initialize(device:) @device = device end |
Class Method Details
.find_device(name_patterns:) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/fusuma/plugin/sendkey/keyboard.rb', line 27 def self.find_device(name_patterns:) Fusuma::Device.reset Array(name_patterns).each do |name_pattern| fusuma_device = Fusuma::Device.all.find { |d| next unless d.capabilities.include?("keyboard") d.name.match(/#{name_pattern}/) } 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" end exit(1) end |
Instance Method Details
#capabilities ⇒ Object
137 138 139 140 141 142 143 144 145 146 |
# File 'lib/fusuma/plugin/sendkey/keyboard.rb', line 137 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 |
#clear_modifiers(keycodes) ⇒ Object
177 178 179 |
# File 'lib/fusuma/plugin/sendkey/keyboard.rb', line 177 def clear_modifiers(keycodes) keycodes.each { |code| send_event(code: code, press: false) } end |
#find_code(code) ⇒ Object
165 166 167 168 169 170 |
# File 'lib/fusuma/plugin/sendkey/keyboard.rb', line 165 def find_code(code) result = capabilities.find { |c| c == code.to_sym } warn_undefined_codes(code) unless result result end |
#key_sync ⇒ Object
127 128 129 130 131 132 133 134 135 |
# File 'lib/fusuma/plugin/sendkey/keyboard.rb', line 127 def key_sync event = Revdev::InputEvent.new( nil, Revdev.const_get(:EV_SYN), Revdev.const_get(:SYN_REPORT), 0 ) @device.write_event(event) end |
#keycode_const(keycode) ⇒ Object
172 173 174 |
# File 'lib/fusuma/plugin/sendkey/keyboard.rb', line 172 def keycode_const(keycode) Object.const_get "Revdev::#{keycode}" end |
#keydown(keycode) ⇒ Object
91 92 93 |
# File 'lib/fusuma/plugin/sendkey/keyboard.rb', line 91 def keydown(keycode) send_event(code: keycode, press: true) end |
#keyup(keycode) ⇒ Object
95 96 97 |
# File 'lib/fusuma/plugin/sendkey/keyboard.rb', line 95 def keyup(keycode) send_event(code: keycode, press: false) end |
#param_to_codes(param) ⇒ Array<String>
183 184 185 |
# File 'lib/fusuma/plugin/sendkey/keyboard.rb', line 183 def param_to_codes(param) param.split("+").map { |keyname| add_prefix(keyname) } end |
#search_codes(code) ⇒ Object
161 162 163 |
# File 'lib/fusuma/plugin/sendkey/keyboard.rb', line 161 def search_codes(code) capabilities.select { |c| c[code] } end |
#send_event(code:, press: true) ⇒ Object
117 118 119 120 121 122 123 124 125 |
# File 'lib/fusuma/plugin/sendkey/keyboard.rb', line 117 def send_event(code:, press: true) event = Revdev::InputEvent.new( nil, Revdev.const_get(:EV_KEY), Revdev.const_get(code), press ? 1 : 0 ) @device.write_event(event) end |
#support?(code) ⇒ Boolean
148 149 150 151 |
# File 'lib/fusuma/plugin/sendkey/keyboard.rb', line 148 def support?(code) @supported_code ||= {} @supported_code[code] ||= find_code(code) end |
#type(param:, keep: "", clear: :none) ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/fusuma/plugin/sendkey/keyboard.rb', line 68 def type(param:, keep: "", clear: :none) return unless param.is_a?(String) 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_codes(clear) end clear_modifiers(clear_keycodes - param_keycodes) type_keycodes.each { |keycode| keydown(keycode) && key_sync && sleep(KEY_INTERVAL) } type_keycodes.reverse_each { |keycode| keyup(keycode) && key_sync && sleep(KEY_INTERVAL) } end |
#types(args) ⇒ Object
52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/fusuma/plugin/sendkey/keyboard.rb', line 52 def types(args) return unless args.is_a?(Array) args.each do |arg| case arg when String type(param: arg) when Hash type(**arg) end end end |
#valid?(params) ⇒ TrueClass, FalseClass
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/fusuma/plugin/sendkey/keyboard.rb', line 101 def valid?(params) return false if params.nil? case params when Array params.all? { |param| valid?(param) } when String param = params keycodes = param_to_codes(param) keycodes.all? { |keycode| support?(keycode) } else MultiLogger.error "sendkey: Invalid config: #{params}" nil end end |
#warn_undefined_codes(code) ⇒ Object
153 154 155 156 157 158 159 |
# File 'lib/fusuma/plugin/sendkey/keyboard.rb', line 153 def warn_undefined_codes(code) candidates = search_codes(code).map { |c| remove_prefix(c.to_s) } warn "Did you mean? #{candidates.join(" / ")}" unless candidates.empty? warn "sendkey: #{remove_prefix(code)} is unsupported." end |