fusuma-plugin-sendkey 0.6.4 → 0.8.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 +4 -4
- data/README.md +18 -1
- data/bin/console +3 -5
- data/fusuma-plugin-sendkey.gemspec +17 -18
- data/lib/fusuma/plugin/executors/sendkey_executor.rb +37 -20
- data/lib/fusuma/plugin/sendkey/device.rb +1 -1
- data/lib/fusuma/plugin/sendkey/keyboard.rb +74 -44
- data/lib/fusuma/plugin/sendkey/version.rb +1 -1
- data/lib/fusuma/plugin/sendkey.rb +2 -2
- metadata +7 -17
- data/spec/fusuma/plugin/executors/sendkey_executor_spec.rb +0 -138
- data/spec/fusuma/plugin/sendkey/keyboard_spec.rb +0 -199
- data/spec/fusuma/plugin/sendkey_spec.rb +0 -7
- data/spec/helpers/config_helper.rb +0 -16
- data/spec/spec_helper.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0512b4f118bd0b676616741f47a643a759d8eb123eb581bb3136b38a34f0acc4
|
4
|
+
data.tar.gz: 45cafd5f8b3f8cd1e44643c20438b04ce59065854548123285ea5eea1e5585fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 264b5e7d2ae3729ccc1f3fe0db02dab1ee1999e089fab2cd2df9f97f3994ff0c20976e37a6e2105c141161dc70db20d4058098529bba5372427bfe242d6d10d5
|
7
|
+
data.tar.gz: b1cb6a075c279a15e63f7685d5887dc0b2c4c767915fb4066b2d929788b725c2d8127d766e5045ee5b1c49f2f40e9882793066e6607f56d2dae967347d89667a
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Fusuma::Plugin::Sendkey [](https://badge.fury.io/rb/fusuma-plugin-sendkey) [](https://badge.fury.io/rb/fusuma-plugin-sendkey) [](https://github.com/iberianpig/fusuma-plugin-sendkey/actions/workflows/main.yml)
|
2
2
|
|
3
3
|
[Fusuma](https://github.com/iberianpig/fusuma) plugin to send keyboard events
|
4
4
|
|
@@ -85,6 +85,20 @@ swipe:
|
|
85
85
|
sendkey: "LEFTCTRL+W" # close tab
|
86
86
|
```
|
87
87
|
|
88
|
+
### clearmodifiers
|
89
|
+
|
90
|
+
- `clearmodifiers: true` option clears other modifier keys before sending
|
91
|
+
|
92
|
+
```yaml
|
93
|
+
swipe:
|
94
|
+
4:
|
95
|
+
up:
|
96
|
+
keypress:
|
97
|
+
LEFTSHIFT:
|
98
|
+
sendkey: "LEFTMETA+DOWN"
|
99
|
+
clearmodifiers: true # clear LEFTSHIFT before sending LEFTMETA+DOWN
|
100
|
+
```
|
101
|
+
|
88
102
|
|
89
103
|
### Specify keyboard by device name
|
90
104
|
|
@@ -105,6 +119,9 @@ plugin:
|
|
105
119
|
device_name: 'YOUR KEYBOARD NAME'
|
106
120
|
```
|
107
121
|
|
122
|
+
**If [fusuma-plugin-remap](https://github.com/iberianpig/fusuma-plugin-remap) is available, it will be automatically connected to `fusuma_virtual_keyboard`, so `device_name` option is not required.**
|
123
|
+
|
124
|
+
|
108
125
|
## Contributing
|
109
126
|
|
110
127
|
Bug reports and pull requests are welcome on GitHub at https://github.com/iberianpig/fusuma-plugin-sendkey. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
data/bin/console
CHANGED
@@ -4,9 +4,7 @@ require "bundler/setup"
|
|
4
4
|
require 'fusuma/plugin/executors/executor'
|
5
5
|
require "fusuma/plugin/sendkey"
|
6
6
|
|
7
|
-
|
8
|
-
# with your gem easier. You can also use a different console, if you like.
|
7
|
+
Fusuma::Plugin::Manager.require_base_plugins
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
Pry.start
|
9
|
+
require "irb"
|
10
|
+
IRB.start(__FILE__)
|
@@ -1,29 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
lib = File.expand_path(
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
-
require
|
5
|
+
require "fusuma/plugin/sendkey/version"
|
6
6
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
|
-
spec.name
|
9
|
-
spec.version
|
10
|
-
spec.authors
|
11
|
-
spec.email
|
8
|
+
spec.name = "fusuma-plugin-sendkey"
|
9
|
+
spec.version = Fusuma::Plugin::Sendkey::VERSION
|
10
|
+
spec.authors = ["iberianpig"]
|
11
|
+
spec.email = ["yhkyky@gmail.com"]
|
12
12
|
|
13
|
-
spec.summary
|
14
|
-
spec.description
|
15
|
-
spec.homepage
|
16
|
-
spec.license
|
13
|
+
spec.summary = "Fusuma plugin to send keyboard events"
|
14
|
+
spec.description = "Fusuma::Plugin::Sendkey emulate keyboard events with evdev"
|
15
|
+
spec.homepage = "https://github.com/iberianpig/fusuma-plugin-sendkey"
|
16
|
+
spec.license = "MIT"
|
17
17
|
|
18
18
|
# Specify which files should be added to the gem when it is released.
|
19
|
-
spec.files
|
20
|
-
spec.
|
21
|
-
spec.
|
22
|
-
spec.
|
23
|
-
spec.
|
24
|
-
spec.required_ruby_version = '>= 2.5.1' # https://packages.ubuntu.com/search?keywords=ruby&searchon=names&exact=1&suite=all§ion=main
|
19
|
+
spec.files = Dir["{bin,lib,exe}/**/*", "LICENSE*", "README*", "*.gemspec"]
|
20
|
+
spec.bindir = "exe"
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
spec.required_ruby_version = ">= 2.5.1" # https://packages.ubuntu.com/search?keywords=ruby&searchon=names&exact=1&suite=all§ion=main
|
25
24
|
# support bionic (18.04LTS) 2.5.1
|
26
25
|
|
27
|
-
spec.add_dependency
|
28
|
-
spec.add_dependency
|
26
|
+
spec.add_dependency "fusuma", "~> 2.0"
|
27
|
+
spec.add_dependency "revdev"
|
29
28
|
end
|
@@ -1,12 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative "../sendkey/keyboard"
|
4
4
|
|
5
5
|
module Fusuma
|
6
6
|
module Plugin
|
7
7
|
module Executors
|
8
|
-
#
|
8
|
+
# Execute to send key event to device
|
9
9
|
class SendkeyExecutor < Executor
|
10
|
+
def initialize
|
11
|
+
@device_name = config_params(:device_name)
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
10
15
|
def execute_keys
|
11
16
|
[:sendkey]
|
12
17
|
end
|
@@ -22,26 +27,18 @@ module Fusuma
|
|
22
27
|
# @return [nil]
|
23
28
|
def execute(event)
|
24
29
|
MultiLogger.info(sendkey: search_param(event))
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
Process.detach(pid)
|
31
|
-
end
|
32
|
-
|
33
|
-
# execute sendkey command
|
34
|
-
# @param event [Event]
|
35
|
-
# @return [nil]
|
36
|
-
def _execute(event)
|
37
|
-
keyboard.type(param: search_param(event))
|
30
|
+
keyboard.type(
|
31
|
+
param: search_param(event),
|
32
|
+
keep: search_keypress(event),
|
33
|
+
clear: clearmodifiers(event)
|
34
|
+
)
|
38
35
|
end
|
39
36
|
|
40
37
|
# check executable
|
41
38
|
# @param event [Event]
|
42
39
|
# @return [TrueClass, FalseClass]
|
43
40
|
def executable?(event)
|
44
|
-
event.tag.end_with?(
|
41
|
+
event.tag.end_with?("_detector") &&
|
45
42
|
event.record.type == :index &&
|
46
43
|
keyboard.valid?(param: search_param(event))
|
47
44
|
end
|
@@ -49,16 +46,36 @@ module Fusuma
|
|
49
46
|
private
|
50
47
|
|
51
48
|
def keyboard
|
52
|
-
@keyboard ||=
|
53
|
-
name_pattren = config_params(:device_name)
|
54
|
-
Sendkey::Keyboard.new(name_pattern: name_pattren)
|
55
|
-
end
|
49
|
+
@keyboard ||= Sendkey::Keyboard.new(name_pattern: @device_name)
|
56
50
|
end
|
57
51
|
|
58
52
|
def search_param(event)
|
59
53
|
index = Config::Index.new([*event.record.index.keys, :sendkey])
|
60
54
|
Config.search(index)
|
61
55
|
end
|
56
|
+
|
57
|
+
# search keypress from config for keep modifiers when sendkey
|
58
|
+
# @param event [Event]
|
59
|
+
# @return [String]
|
60
|
+
def search_keypress(event)
|
61
|
+
# if fusuma_virtual_keyboard exists, don't have to keep modifiers
|
62
|
+
return "" if keyboard.use_virtual_keyboard?
|
63
|
+
|
64
|
+
keys = event.record.index.keys
|
65
|
+
keypress_index = keys.find_index { |k| k.symbol == :keypress }
|
66
|
+
code = keypress_index && keys[keypress_index + 1].symbol
|
67
|
+
code.to_s
|
68
|
+
end
|
69
|
+
|
70
|
+
# clearmodifiers from config
|
71
|
+
# @param event [Event]
|
72
|
+
# @return [String, TrueClass, Symbole]
|
73
|
+
def clearmodifiers(event)
|
74
|
+
@clearmodifiers ||= {}
|
75
|
+
index = event.record.index
|
76
|
+
@clearmodifiers[index.cache_key] ||=
|
77
|
+
Config.search(Config::Index.new([*index.keys, "clearmodifiers"])) || :none
|
78
|
+
end
|
62
79
|
end
|
63
80
|
end
|
64
81
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "revdev"
|
4
|
+
require "fusuma/device"
|
5
5
|
|
6
|
-
require_relative
|
6
|
+
require_relative "./device"
|
7
7
|
|
8
8
|
module Fusuma
|
9
9
|
module Plugin
|
@@ -24,120 +24,150 @@ module Fusuma
|
|
24
24
|
KEY_RIGHTMETA
|
25
25
|
].freeze
|
26
26
|
|
27
|
+
DEFAULT_NAME_PATTERN = "keyboard|Keyboard|KEYBOARD"
|
28
|
+
VIRTUAL_KEYBOARD = "fusuma_virtual_keyboard" # fusuma-plugin-remap creates uinput device
|
29
|
+
|
27
30
|
def self.find_device(name_pattern:)
|
31
|
+
Fusuma::Device.reset
|
28
32
|
Fusuma::Device.all.find { |d| d.name.match(/#{name_pattern}/) }
|
29
33
|
end
|
30
34
|
|
31
35
|
def initialize(name_pattern: nil)
|
32
|
-
|
33
|
-
|
36
|
+
device = if name_pattern
|
37
|
+
Keyboard.find_device(name_pattern: name_pattern)
|
38
|
+
else
|
39
|
+
Keyboard.find_device(name_pattern: VIRTUAL_KEYBOARD) || Keyboard.find_device(name_pattern: DEFAULT_NAME_PATTERN)
|
40
|
+
end
|
34
41
|
|
35
42
|
if device.nil?
|
36
43
|
warn "sendkey: Keyboard: /#{name_pattern}/ is not found"
|
37
44
|
exit(1)
|
38
45
|
end
|
46
|
+
MultiLogger.info "sendkey: Keyboard: #{device.name}"
|
39
47
|
|
48
|
+
@use_virtual_keyboard = device.name.match(/#{VIRTUAL_KEYBOARD}/o)
|
40
49
|
@device = Device.new(path: "/dev/input/#{device.id}")
|
41
50
|
end
|
42
51
|
|
43
|
-
|
52
|
+
def use_virtual_keyboard?
|
53
|
+
@use_virtual_keyboard
|
54
|
+
end
|
44
55
|
|
45
|
-
# @param param [String]
|
46
|
-
# @param keep [String]
|
47
|
-
|
56
|
+
# @param param [String] key names separated by '+' to type
|
57
|
+
# @param keep [String] key names separated by '+' to keep
|
58
|
+
# @param clear [String, Symbol, TrueClass] key names separated by '+' to clear or :all to relase all modifiers
|
59
|
+
def type(param:, keep: "", clear: :none)
|
48
60
|
return unless param.is_a?(String)
|
49
61
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
62
|
+
param_keycodes = param_to_keycodes(param)
|
63
|
+
type_keycodes = param_keycodes - param_to_keycodes(keep)
|
64
|
+
|
65
|
+
clear_keycodes =
|
66
|
+
case clear
|
67
|
+
when true
|
68
|
+
MODIFIER_KEY_CODES
|
69
|
+
when :none, false
|
70
|
+
[]
|
71
|
+
else
|
72
|
+
# release keys specified by clearmodifiers
|
73
|
+
param_to_keycodes(clear)
|
74
|
+
end
|
75
|
+
|
76
|
+
clear_modifiers(clear_keycodes - param_keycodes)
|
77
|
+
|
78
|
+
type_keycodes.each { |keycode| keydown(keycode) && key_sync }
|
79
|
+
type_keycodes.reverse_each { |keycode| keyup(keycode) && key_sync }
|
80
|
+
end
|
81
|
+
|
82
|
+
def keydown(keycode)
|
83
|
+
send_event(code: keycode, press: true)
|
84
|
+
end
|
85
|
+
|
86
|
+
def keyup(keycode)
|
87
|
+
send_event(code: keycode, press: false)
|
56
88
|
end
|
57
89
|
|
58
90
|
# @param param [String]
|
59
91
|
def valid?(param:)
|
60
92
|
return unless param.is_a?(String)
|
61
93
|
|
62
|
-
keycodes =
|
94
|
+
keycodes = param_to_keycodes(param)
|
63
95
|
keycodes.all? { |keycode| support?(keycode) }
|
64
96
|
end
|
65
97
|
|
66
|
-
def
|
98
|
+
def send_event(code:, press: true)
|
67
99
|
event = Revdev::InputEvent.new(
|
68
100
|
nil,
|
69
101
|
Revdev.const_get(:EV_KEY),
|
70
|
-
Revdev.const_get(
|
102
|
+
Revdev.const_get(code),
|
71
103
|
press ? 1 : 0
|
72
104
|
)
|
73
105
|
@device.write_event(event)
|
74
106
|
end
|
75
107
|
|
76
|
-
def key_sync
|
108
|
+
def key_sync
|
77
109
|
event = Revdev::InputEvent.new(
|
78
110
|
nil,
|
79
111
|
Revdev.const_get(:EV_SYN),
|
80
112
|
Revdev.const_get(:SYN_REPORT),
|
81
|
-
|
113
|
+
0
|
82
114
|
)
|
83
115
|
@device.write_event(event)
|
116
|
+
sleep(INTERVAL)
|
84
117
|
end
|
85
118
|
|
86
119
|
def support?(keycode)
|
87
120
|
@supported_code ||= {}
|
88
|
-
@supported_code[keycode] ||=
|
89
|
-
true
|
90
|
-
else
|
91
|
-
search_candidates(keycode: keycode)
|
92
|
-
end
|
121
|
+
@supported_code[keycode] ||= find_code(keycode: keycode)
|
93
122
|
end
|
94
123
|
|
95
|
-
def
|
96
|
-
query = keycode&.upcase&.gsub(
|
124
|
+
def warn_undefined_codes(keycode:)
|
125
|
+
query = keycode&.upcase&.gsub("KEY_", "")
|
97
126
|
|
98
127
|
candidates = search_codes(query: query)
|
99
128
|
|
100
|
-
warn "Did you mean? #{candidates.join(
|
129
|
+
warn "Did you mean? #{candidates.join(" / ")}" unless candidates.empty?
|
101
130
|
warn "sendkey: #{remove_prefix(keycode)} is unsupported."
|
102
131
|
end
|
103
132
|
|
104
133
|
def search_codes(query: nil)
|
105
134
|
Revdev.constants
|
106
|
-
|
107
|
-
|
135
|
+
.select { |c| c[/KEY_.*#{query}.*/] }
|
136
|
+
.map { |c| c.to_s.gsub("KEY_", "") }
|
108
137
|
end
|
109
138
|
|
110
139
|
def find_code(keycode: nil)
|
111
|
-
query = keycode&.upcase&.gsub(
|
140
|
+
query = keycode&.upcase&.gsub("KEY_", "")
|
141
|
+
|
142
|
+
result = Revdev.constants.find { |c| c == "KEY_#{query}".to_sym }
|
112
143
|
|
113
|
-
|
144
|
+
warn_undefined_codes(keycode: keycode) unless result
|
145
|
+
result
|
114
146
|
end
|
115
147
|
|
116
148
|
def keycode_const(keycode)
|
117
|
-
Object.const_get "
|
149
|
+
Object.const_get "Revdev::#{keycode}"
|
118
150
|
end
|
119
151
|
|
120
152
|
# @param [Array<String>] keycodes to be released
|
121
153
|
def clear_modifiers(keycodes)
|
122
|
-
keycodes.each { |code|
|
154
|
+
keycodes.each { |code| send_event(code: code, press: false) }
|
123
155
|
end
|
124
156
|
|
125
|
-
|
126
|
-
|
127
|
-
def
|
128
|
-
param.split(
|
157
|
+
# @param [String]
|
158
|
+
# @return [Array<String>]
|
159
|
+
def param_to_keycodes(param)
|
160
|
+
param.split("+").map { |keyname| add_key_prefix(keyname) }
|
129
161
|
end
|
130
162
|
|
131
|
-
|
163
|
+
private
|
164
|
+
|
165
|
+
def add_key_prefix(code)
|
132
166
|
"KEY_#{code.upcase}"
|
133
167
|
end
|
134
168
|
|
135
169
|
def remove_prefix(keycode)
|
136
|
-
keycode.gsub(
|
137
|
-
end
|
138
|
-
|
139
|
-
def wait
|
140
|
-
sleep(INTERVAL)
|
170
|
+
keycode.gsub("KEY_", "")
|
141
171
|
end
|
142
172
|
end
|
143
173
|
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.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- iberianpig
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-08-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fusuma
|
@@ -57,16 +57,11 @@ files:
|
|
57
57
|
- lib/fusuma/plugin/sendkey/device.rb
|
58
58
|
- lib/fusuma/plugin/sendkey/keyboard.rb
|
59
59
|
- lib/fusuma/plugin/sendkey/version.rb
|
60
|
-
- spec/fusuma/plugin/executors/sendkey_executor_spec.rb
|
61
|
-
- spec/fusuma/plugin/sendkey/keyboard_spec.rb
|
62
|
-
- spec/fusuma/plugin/sendkey_spec.rb
|
63
|
-
- spec/helpers/config_helper.rb
|
64
|
-
- spec/spec_helper.rb
|
65
60
|
homepage: https://github.com/iberianpig/fusuma-plugin-sendkey
|
66
61
|
licenses:
|
67
62
|
- MIT
|
68
63
|
metadata: {}
|
69
|
-
post_install_message:
|
64
|
+
post_install_message:
|
70
65
|
rdoc_options: []
|
71
66
|
require_paths:
|
72
67
|
- lib
|
@@ -81,13 +76,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
81
76
|
- !ruby/object:Gem::Version
|
82
77
|
version: '0'
|
83
78
|
requirements: []
|
84
|
-
rubygems_version: 3.
|
85
|
-
signing_key:
|
79
|
+
rubygems_version: 3.3.26
|
80
|
+
signing_key:
|
86
81
|
specification_version: 4
|
87
82
|
summary: Fusuma plugin to send keyboard events
|
88
|
-
test_files:
|
89
|
-
- spec/fusuma/plugin/executors/sendkey_executor_spec.rb
|
90
|
-
- spec/fusuma/plugin/sendkey/keyboard_spec.rb
|
91
|
-
- spec/fusuma/plugin/sendkey_spec.rb
|
92
|
-
- spec/helpers/config_helper.rb
|
93
|
-
- spec/spec_helper.rb
|
83
|
+
test_files: []
|
@@ -1,138 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
require 'fusuma/plugin/executors/executor'
|
6
|
-
require 'fusuma/plugin/events/event'
|
7
|
-
require 'fusuma/plugin/events/records/index_record'
|
8
|
-
|
9
|
-
require './lib/fusuma/plugin/executors/sendkey_executor'
|
10
|
-
|
11
|
-
module Fusuma
|
12
|
-
module Plugin
|
13
|
-
module Executors
|
14
|
-
RSpec.describe SendkeyExecutor do
|
15
|
-
around do |example|
|
16
|
-
ConfigHelper.load_config_yml = <<~CONFIG
|
17
|
-
dummy:
|
18
|
-
1:
|
19
|
-
direction:
|
20
|
-
sendkey: KEY_CODE
|
21
|
-
|
22
|
-
plugin:
|
23
|
-
executors:
|
24
|
-
sendkey_executor:
|
25
|
-
device_name: dummy
|
26
|
-
CONFIG
|
27
|
-
|
28
|
-
example.run
|
29
|
-
|
30
|
-
Config.custom_path = nil
|
31
|
-
end
|
32
|
-
|
33
|
-
before do
|
34
|
-
index = Config::Index.new([:dummy, 1, :direction])
|
35
|
-
record = Events::Records::IndexRecord.new(index: index)
|
36
|
-
@event = Events::Event.new(tag: 'dummy_detector', record: record)
|
37
|
-
@executor = described_class.new
|
38
|
-
|
39
|
-
@keyboard = instance_double(Sendkey::Keyboard)
|
40
|
-
|
41
|
-
allow(@executor).to receive(:keyboard).and_return @keyboard
|
42
|
-
end
|
43
|
-
|
44
|
-
describe '#execute' do
|
45
|
-
before do
|
46
|
-
allow(Process).to receive(:daemon).with(true)
|
47
|
-
allow(Process).to receive(:detach).with(anything)
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'fork' do
|
51
|
-
expect(@executor).to receive(:fork).and_yield do |block_context|
|
52
|
-
expect(block_context).to receive(:_execute).with(@event)
|
53
|
-
end
|
54
|
-
|
55
|
-
@executor.execute(@event)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
describe '#_execute' do
|
60
|
-
it 'send KEY_CODE message to keybard' do
|
61
|
-
allow(@executor).to receive(:search_param).with(@event).and_return('KEY_CODE')
|
62
|
-
expect(@keyboard).to receive(:type).with(param: 'KEY_CODE')
|
63
|
-
@executor._execute(@event)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
describe '#executable?' do
|
68
|
-
before do
|
69
|
-
allow(@keyboard).to receive(:valid?).with(param: 'MODIFIER_CODE+KEY_CODE')
|
70
|
-
.and_return true
|
71
|
-
allow(@keyboard).to receive(:valid?).with(param: 'KEY_CODE')
|
72
|
-
.and_return true
|
73
|
-
allow(@keyboard).to receive(:valid?).with(param: 'INVALID_CODE')
|
74
|
-
.and_return false
|
75
|
-
end
|
76
|
-
|
77
|
-
context 'when given valid event tagged as xxxx_detector' do
|
78
|
-
it { expect(@executor).to be_executable(@event) }
|
79
|
-
end
|
80
|
-
|
81
|
-
context 'when given INVALID event tagged as invalid_tag' do
|
82
|
-
before do
|
83
|
-
@event.tag = 'invalid_tag'
|
84
|
-
end
|
85
|
-
|
86
|
-
it { expect(@executor).not_to be_executable(@event) }
|
87
|
-
end
|
88
|
-
|
89
|
-
context "when sendkey: 'MODIFIER_CODE+KEY_CODE'" do
|
90
|
-
around do |example|
|
91
|
-
ConfigHelper.load_config_yml = <<~CONFIG
|
92
|
-
dummy:
|
93
|
-
1:
|
94
|
-
direction:
|
95
|
-
sendkey: 'MODIFIER_CODE+KEY_CODE'
|
96
|
-
plugin:
|
97
|
-
executors:
|
98
|
-
sendkey_executor:
|
99
|
-
device_name: dummy
|
100
|
-
CONFIG
|
101
|
-
|
102
|
-
example.run
|
103
|
-
|
104
|
-
Config.custom_path = nil
|
105
|
-
end
|
106
|
-
|
107
|
-
it 'returns true' do
|
108
|
-
expect(@executor).to be_executable(@event)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
context "when sendkey: 'INVALID_CODE'" do
|
113
|
-
around do |example|
|
114
|
-
ConfigHelper.load_config_yml = <<~CONFIG
|
115
|
-
dummy:
|
116
|
-
1:
|
117
|
-
direction:
|
118
|
-
sendkey: 'INVALID_CODE'
|
119
|
-
plugin:
|
120
|
-
executors:
|
121
|
-
sendkey_executor:
|
122
|
-
device_name: dummy
|
123
|
-
CONFIG
|
124
|
-
|
125
|
-
example.run
|
126
|
-
|
127
|
-
Config.custom_path = nil
|
128
|
-
end
|
129
|
-
|
130
|
-
it 'returns true' do
|
131
|
-
expect(@executor).not_to be_executable(@event)
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
@@ -1,199 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
require './lib/fusuma/plugin/sendkey/keyboard'
|
6
|
-
|
7
|
-
module Fusuma
|
8
|
-
module Plugin
|
9
|
-
module Sendkey
|
10
|
-
RSpec.describe Keyboard do
|
11
|
-
describe '#new' do
|
12
|
-
context 'when keyboard is found' do
|
13
|
-
before do
|
14
|
-
dummy_keyboard = Fusuma::Device.new(name: 'dummy keyboard')
|
15
|
-
allow(described_class)
|
16
|
-
.to receive(:find_device)
|
17
|
-
.and_return(dummy_keyboard)
|
18
|
-
allow(Sendkey::Device).to receive(:new).and_return('dummy')
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'does not raise error' do
|
22
|
-
expect { described_class.new }.not_to raise_error
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
context 'when keyboard is not found' do
|
27
|
-
before do
|
28
|
-
allow(described_class)
|
29
|
-
.to receive(:find_device)
|
30
|
-
.and_return(nil)
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'does not raise error' do
|
34
|
-
expect { described_class.new }.to raise_error SystemExit
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
context 'when detected device name is Keyboard (Capitarized)' do
|
39
|
-
before do
|
40
|
-
other_device = Fusuma::Device.new(name: 'Keyboard', id: 'dummy')
|
41
|
-
|
42
|
-
allow(described_class)
|
43
|
-
.to receive(:find_device)
|
44
|
-
.and_return(other_device)
|
45
|
-
allow(Sendkey::Device).to receive(:new).and_return('dummy')
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'does not raise error' do
|
49
|
-
expect { described_class.new }.not_to raise_error
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
context 'when detected device name is KEYBOARD (Upper case)' do
|
54
|
-
before do
|
55
|
-
other_device = Fusuma::Device.new(name: 'KEYBOARD', id: 'dummy')
|
56
|
-
allow(described_class)
|
57
|
-
.to receive(:find_device)
|
58
|
-
.and_return(other_device)
|
59
|
-
allow(Sendkey::Device).to receive(:new).and_return('dummy')
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'does not raise error' do
|
63
|
-
expect { described_class.new }.not_to raise_error
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
context 'with given name pattern' do
|
68
|
-
before do
|
69
|
-
specified_device = Fusuma::Device.new(
|
70
|
-
name: 'Awesome KEY/BOARD input device',
|
71
|
-
id: 'dummy'
|
72
|
-
)
|
73
|
-
allow(Fusuma::Device).to receive(:all).and_return([specified_device])
|
74
|
-
allow(Sendkey::Device).to receive(:new).and_return('dummy')
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'does not raise error' do
|
78
|
-
expect { described_class.new(name_pattern: 'Awesome KEY/BOARD') }.not_to raise_error
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
context 'when name pattern (use default) is not given' do
|
83
|
-
subject { -> { described_class.new(name_pattern: nil) } }
|
84
|
-
|
85
|
-
before do
|
86
|
-
allow(Sendkey::Device).to receive(:new).and_return('dummy')
|
87
|
-
end
|
88
|
-
|
89
|
-
context 'when exist device named keyboard(lower-case)' do
|
90
|
-
before do
|
91
|
-
specified_device = Fusuma::Device.new(
|
92
|
-
name: 'keyboard',
|
93
|
-
id: 'dummy'
|
94
|
-
)
|
95
|
-
allow(Fusuma::Device).to receive(:all).and_return([specified_device])
|
96
|
-
end
|
97
|
-
|
98
|
-
it { is_expected.not_to raise_error }
|
99
|
-
end
|
100
|
-
|
101
|
-
context 'when exist device named Keyboard(Capital-case)' do
|
102
|
-
before do
|
103
|
-
specified_device = Fusuma::Device.new(
|
104
|
-
name: 'Keyboard',
|
105
|
-
id: 'dummy'
|
106
|
-
)
|
107
|
-
allow(Fusuma::Device).to receive(:all).and_return([specified_device])
|
108
|
-
end
|
109
|
-
|
110
|
-
it { is_expected.not_to raise_error }
|
111
|
-
end
|
112
|
-
|
113
|
-
context 'when exist device named KEYBOARD(UPPER case)' do
|
114
|
-
before do
|
115
|
-
specified_device = Fusuma::Device.new(
|
116
|
-
name: 'KEYBOARD',
|
117
|
-
id: 'dummy'
|
118
|
-
)
|
119
|
-
allow(Fusuma::Device).to receive(:all).and_return([specified_device])
|
120
|
-
end
|
121
|
-
|
122
|
-
it { is_expected.not_to raise_error }
|
123
|
-
end
|
124
|
-
|
125
|
-
context 'when exist no device named keyboard|Keyboard|KEYBOARD' do
|
126
|
-
before do
|
127
|
-
specified_device = Fusuma::Device.new(
|
128
|
-
name: 'KEY-BOARD',
|
129
|
-
id: 'dummy'
|
130
|
-
)
|
131
|
-
allow(Fusuma::Device).to receive(:all).and_return([specified_device])
|
132
|
-
end
|
133
|
-
|
134
|
-
it { is_expected.to raise_error(SystemExit) }
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
describe '#type' do
|
140
|
-
before do
|
141
|
-
allow(described_class)
|
142
|
-
.to receive(:find_device)
|
143
|
-
.and_return(Fusuma::Device.new(name: 'dummy keyboard'))
|
144
|
-
|
145
|
-
@device = instance_double(Sendkey::Device)
|
146
|
-
allow(@device).to receive(:write_event).with(anything)
|
147
|
-
# allow(@device).to receive(:valid?).with(param: 'KEY_A')
|
148
|
-
|
149
|
-
allow(Sendkey::Device).to receive(:new).and_return(@device)
|
150
|
-
|
151
|
-
@keyboard = described_class.new
|
152
|
-
end
|
153
|
-
|
154
|
-
it 'presses key KEY_A and release KEY_A' do
|
155
|
-
expect(@keyboard).to receive(:clear_modifiers).ordered
|
156
|
-
expect(@keyboard).to receive(:key_event).with(keycode: 'KEY_A', press: true).ordered
|
157
|
-
expect(@keyboard).to receive(:key_event).with(keycode: 'KEY_A', press: false).ordered
|
158
|
-
@keyboard.type(param: 'A')
|
159
|
-
end
|
160
|
-
|
161
|
-
context 'with modifier keys' do
|
162
|
-
before do
|
163
|
-
@keys = 'LEFTSHIFT+A'
|
164
|
-
end
|
165
|
-
|
166
|
-
it 'clear all modifier keys except parameter of sendkey' do
|
167
|
-
expect(@keyboard).to receive(:clear_modifiers).with(Keyboard::MODIFIER_KEY_CODES - ['KEY_LEFTSHIFT']).ordered
|
168
|
-
@keyboard.type(param: @keys)
|
169
|
-
end
|
170
|
-
|
171
|
-
it 'types (Shift)A' do
|
172
|
-
expect(@keyboard).to receive(:clear_modifiers).ordered
|
173
|
-
expect(@keyboard).to receive(:key_event).with(keycode: 'KEY_LEFTSHIFT', press: true).ordered
|
174
|
-
expect(@keyboard).to receive(:key_event).with(keycode: 'KEY_A', press: true).ordered
|
175
|
-
expect(@keyboard).to receive(:key_event).with(keycode: 'KEY_A', press: false).ordered
|
176
|
-
expect(@keyboard).to receive(:key_event).with(keycode: 'KEY_LEFTSHIFT', press: false).ordered
|
177
|
-
@keyboard.type(param: @keys)
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
context 'with multiple keys' do
|
182
|
-
before do
|
183
|
-
@keys = 'A+B'
|
184
|
-
end
|
185
|
-
|
186
|
-
it 'types AB' do
|
187
|
-
expect(@keyboard).to receive(:clear_modifiers).ordered
|
188
|
-
expect(@keyboard).to receive(:key_event).with(keycode: 'KEY_A', press: true).ordered
|
189
|
-
expect(@keyboard).to receive(:key_event).with(keycode: 'KEY_B', press: true).ordered
|
190
|
-
expect(@keyboard).to receive(:key_event).with(keycode: 'KEY_B', press: false).ordered
|
191
|
-
expect(@keyboard).to receive(:key_event).with(keycode: 'KEY_A', press: false).ordered
|
192
|
-
@keyboard.type(param: @keys)
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'tempfile'
|
4
|
-
require 'fusuma/config'
|
5
|
-
|
6
|
-
module Fusuma
|
7
|
-
module ConfigHelper
|
8
|
-
module_function
|
9
|
-
|
10
|
-
def load_config_yml=(string)
|
11
|
-
Config.custom_path = Tempfile.open do |temp_file|
|
12
|
-
temp_file.tap { |f| f.write(string) }
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'bundler/setup'
|
4
|
-
require 'helpers/config_helper'
|
5
|
-
|
6
|
-
RSpec.configure do |config|
|
7
|
-
# Enable flags like --only-failures and --next-failure
|
8
|
-
config.example_status_persistence_file_path = '.rspec_status'
|
9
|
-
|
10
|
-
# Disable RSpec exposing methods globally on `Module` and `main`
|
11
|
-
config.disable_monkey_patching!
|
12
|
-
|
13
|
-
config.expect_with :rspec do |c|
|
14
|
-
c.syntax = :expect
|
15
|
-
end
|
16
|
-
|
17
|
-
config.include(Fusuma::ConfigHelper)
|
18
|
-
end
|