fusuma-plugin-sendkey 0.2.1 → 0.3.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 +6 -5
- data/bin/console +3 -5
- data/exe/fusuma-sendkey +3 -4
- data/fusuma-plugin-sendkey.gemspec +3 -2
- data/lib/fusuma/plugin/executors/sendkey_executor.rb +5 -11
- data/lib/fusuma/plugin/sendkey/device.rb +7 -34
- data/lib/fusuma/plugin/sendkey/keyboard.rb +82 -21
- data/lib/fusuma/plugin/sendkey/version.rb +1 -1
- metadata +23 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d27660bea09b33620ab905e3b112cf0f9884b3617097daadd6d8ca03d2d5c14b
|
4
|
+
data.tar.gz: 70b1f7ddffaa8d874a44feaec361c60d0bca6744f30ec6a5c6f3c3efb1fe2a9f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0257fa54b43876536bb7729c74f05ff06d0a12e57885b5d544b9bdd209815780811496296339efca5353102f14fb811c1be7b82839b51542463c3cbbc90ad6b4
|
7
|
+
data.tar.gz: '049d2d9cf06c538800189db3addb7508e4c98a4390c3da8eb1a41dae2eb007fe11246fbfb86fe2ac76c131a81c7fa7255d2f7951f23d37fea92780920761617a'
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
[Fusuma](https://github.com/iberianpig/fusuma) plugin that sending virtual keyboard events
|
4
4
|
|
5
|
-
*
|
5
|
+
* Send keyboard events with writing event /dev/input/eventN
|
6
6
|
* This plugin is wayland compatible and alternative to xdotool
|
7
7
|
|
8
8
|
## Installation
|
@@ -12,7 +12,7 @@ Run the following code in your terminal.
|
|
12
12
|
### Install dependencies
|
13
13
|
|
14
14
|
```sh
|
15
|
-
$ sudo apt-get install
|
15
|
+
$ sudo apt-get install libevdev-dev ruby-ffi
|
16
16
|
```
|
17
17
|
|
18
18
|
### Install fusuma-plugin-sendkey
|
@@ -22,7 +22,7 @@ $ sudo gem install fusuma-plugin-sendkey
|
|
22
22
|
```
|
23
23
|
|
24
24
|
|
25
|
-
## List
|
25
|
+
## List available keys
|
26
26
|
|
27
27
|
```sh
|
28
28
|
$ fusuma-sendkey -l
|
@@ -30,12 +30,13 @@ $ fusuma-sendkey -l
|
|
30
30
|
|
31
31
|
## Run fusuma-sendkey on Terminal
|
32
32
|
|
33
|
-
* `fusuma-sendkey`
|
33
|
+
* `fusuma-sendkey` command is available on your terminal
|
34
|
+
* `fusuma-sendkey` can send multiple key events
|
34
35
|
* Combine keys for pressing the same time with `+`
|
35
36
|
|
36
37
|
|
37
38
|
```sh
|
38
|
-
$ fusuma-sendkey LEFTCTRL+T
|
39
|
+
$ fusuma-sendkey LEFTCTRL+T # press ctrl key + t key
|
39
40
|
```
|
40
41
|
|
41
42
|
|
data/bin/console
CHANGED
@@ -1,14 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require "bundler/setup"
|
4
|
+
require 'fusuma/plugin/executors/executor'
|
4
5
|
require "fusuma/plugin/sendkey"
|
5
6
|
|
6
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
8
|
# with your gem easier. You can also use a different console, if you like.
|
8
9
|
|
9
10
|
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start(__FILE__)
|
11
|
+
require "pry"
|
12
|
+
Pry.start
|
data/exe/fusuma-sendkey
CHANGED
@@ -20,7 +20,7 @@ end
|
|
20
20
|
opt.parse!(ARGV)
|
21
21
|
|
22
22
|
if option[:list]
|
23
|
-
puts Fusuma::Plugin::Sendkey::Keyboard.new.
|
23
|
+
puts Fusuma::Plugin::Sendkey::Keyboard.new.search_codes
|
24
24
|
return
|
25
25
|
end
|
26
26
|
|
@@ -37,6 +37,5 @@ if param.nil?
|
|
37
37
|
exit 1
|
38
38
|
end
|
39
39
|
|
40
|
-
Fusuma::Plugin::Sendkey::Keyboard.new
|
41
|
-
|
42
|
-
end
|
40
|
+
keyboard = Fusuma::Plugin::Sendkey::Keyboard.new
|
41
|
+
keyboard.valid?(param: param) && keyboard.type(param: param)
|
@@ -24,8 +24,9 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
25
25
|
spec.require_paths = ['lib']
|
26
26
|
|
27
|
-
spec.add_dependency 'evdev'
|
28
|
-
spec.add_dependency 'fusuma', '~> 1.5
|
27
|
+
spec.add_dependency 'evdev', '~> 1.0'
|
28
|
+
spec.add_dependency 'fusuma', '~> 1.5'
|
29
|
+
spec.add_dependency 'linux_input', '~> 1.1'
|
29
30
|
|
30
31
|
spec.add_development_dependency 'bundler'
|
31
32
|
spec.add_development_dependency 'github_changelog_generator', '~> 1.14'
|
@@ -17,12 +17,10 @@ module Fusuma
|
|
17
17
|
# @param event [Event]
|
18
18
|
# @return [nil]
|
19
19
|
def execute(event)
|
20
|
-
return if search_command(event).nil?
|
21
|
-
|
22
20
|
MultiLogger.info(sendkey: search_param(event))
|
23
21
|
pid = fork do
|
24
22
|
Process.daemon(true)
|
25
|
-
|
23
|
+
keyboard.type(param: search_param(event))
|
26
24
|
end
|
27
25
|
|
28
26
|
Process.detach(pid)
|
@@ -34,22 +32,18 @@ module Fusuma
|
|
34
32
|
def executable?(event)
|
35
33
|
event.tag.end_with?('_detector') &&
|
36
34
|
event.record.type == :index &&
|
37
|
-
|
35
|
+
keyboard.valid?(param: search_param(event))
|
38
36
|
end
|
39
37
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def search_command(event)
|
38
|
+
private
|
39
|
+
|
40
|
+
def keyboard
|
44
41
|
@keyboard ||= begin
|
45
42
|
device = Sendkey::Device.new(path: config_params(:device_path))
|
46
43
|
Sendkey::Keyboard.new(device: device)
|
47
44
|
end
|
48
|
-
@keyboard.type_command(param: search_param(event))
|
49
45
|
end
|
50
46
|
|
51
|
-
private
|
52
|
-
|
53
47
|
def search_param(event)
|
54
48
|
index = Config::Index.new([*event.record.index.keys, :sendkey])
|
55
49
|
Config.search(index)
|
@@ -7,18 +7,16 @@ module Fusuma
|
|
7
7
|
module Sendkey
|
8
8
|
# handle Evdev device
|
9
9
|
class Device
|
10
|
-
attr_reader :device_id
|
11
10
|
def initialize(path: nil)
|
12
11
|
return if path && (@evdev = Evdev.new(path))
|
13
12
|
|
14
13
|
(0..99).lazy.find do |i|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
14
|
+
evdev = Evdev.new("/dev/input/event#{i}")
|
15
|
+
# NOTE: find keyboard device
|
16
|
+
@evdev = evdev if evdev.supports_event?('KEY_LEFTALT')
|
17
|
+
rescue Errno::ENOENT # No such file or directory
|
18
|
+
false
|
19
|
+
# TODO: rescue Errno::EACCES
|
22
20
|
end
|
23
21
|
end
|
24
22
|
|
@@ -28,36 +26,11 @@ module Fusuma
|
|
28
26
|
@path ||= @evdev.file.path
|
29
27
|
end
|
30
28
|
|
31
|
-
def support?(
|
32
|
-
keycode = convert_keycode(code)
|
29
|
+
def support?(keycode)
|
33
30
|
@evdev.supports_event?(keycode)
|
34
31
|
rescue NameError
|
35
|
-
candidates = search_codes(code: code)
|
36
|
-
|
37
|
-
warn "Did you mean? #{candidates.join(' / ')}" unless candidates.empty?
|
38
|
-
|
39
32
|
false
|
40
33
|
end
|
41
|
-
|
42
|
-
def search_codes(code: nil)
|
43
|
-
query = code&.upcase
|
44
|
-
LinuxInput.constants
|
45
|
-
.select { |c| c[/KEY_.*#{query}.*/] }
|
46
|
-
.select { |c| @evdev.supports_event?(c) }
|
47
|
-
.map { |c| c.to_s.gsub('KEY_', '') }
|
48
|
-
end
|
49
|
-
|
50
|
-
def emulate(code:, press: true)
|
51
|
-
keycode = convert_keycode(code)
|
52
|
-
v = press ? 1 : 0
|
53
|
-
"evemu-event #{path} --type EV_KEY --code #{keycode} --value #{v} --sync"
|
54
|
-
end
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
def convert_keycode(code)
|
59
|
-
"KEY_#{code.upcase}"
|
60
|
-
end
|
61
34
|
end
|
62
35
|
end
|
63
36
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'linux_input'
|
4
|
+
require 'fcntl'
|
3
5
|
require_relative './device.rb'
|
4
6
|
|
5
7
|
module Fusuma
|
@@ -12,41 +14,100 @@ module Fusuma
|
|
12
14
|
end
|
13
15
|
|
14
16
|
# @param param [String]
|
15
|
-
def
|
17
|
+
def type(param:)
|
16
18
|
return unless param.is_a?(String)
|
17
19
|
|
18
|
-
|
19
|
-
press_commands = codes.map { |code| press_command(code) }
|
20
|
-
release_commands = codes.reverse.map { |code| release_command(code) }
|
20
|
+
keycodes = split_param(param)
|
21
21
|
|
22
|
-
|
22
|
+
clear_modifiers
|
23
|
+
keycodes.each { |keycode| key_event(keycode: keycode, press: true) }
|
24
|
+
key_sync(press: true)
|
25
|
+
keycodes.reverse.map { |keycode| key_event(keycode: keycode, press: false) }
|
26
|
+
key_sync(press: false)
|
27
|
+
device_file.close
|
23
28
|
end
|
24
29
|
|
25
|
-
|
26
|
-
|
30
|
+
# @param param [String]
|
31
|
+
def valid?(param:)
|
32
|
+
return unless param.is_a?(String)
|
33
|
+
|
34
|
+
keycodes = split_param(param)
|
35
|
+
keycodes.all? { |keycode| support?(keycode) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def device_file
|
39
|
+
return @device_file if @device_file && !@device_file.closed?
|
27
40
|
|
28
|
-
@device.
|
41
|
+
@device_file = File.open(@device.path, Fcntl::O_WRONLY | Fcntl::O_NDELAY)
|
29
42
|
end
|
30
43
|
|
31
|
-
def
|
32
|
-
|
44
|
+
def key_event(keycode:, press: true)
|
45
|
+
event = LinuxInput::InputEvent.new
|
46
|
+
event[:time] = LinuxInput::Timeval.new
|
47
|
+
event[:time][:tv_sec] = Time.now.to_i
|
48
|
+
event[:type] = LinuxInput::EV_KEY
|
49
|
+
event[:code] = keycode_const(keycode)
|
50
|
+
event[:value] = press ? 1 : 0
|
51
|
+
device_file.syswrite(event.pointer.read_bytes(event.size))
|
52
|
+
end
|
33
53
|
|
34
|
-
|
54
|
+
def key_sync(press: true)
|
55
|
+
event = LinuxInput::InputEvent.new
|
56
|
+
event[:time] = LinuxInput::Timeval.new
|
57
|
+
event[:time][:tv_sec] = Time.now.to_i
|
58
|
+
event[:type] = LinuxInput::EV_SYN
|
59
|
+
event[:code] = LinuxInput::SYN_REPORT
|
60
|
+
event[:value] = press ? 1 : 0
|
61
|
+
device_file.syswrite(event.pointer.read_bytes(event.size))
|
35
62
|
end
|
36
63
|
|
37
|
-
def support?(
|
64
|
+
def support?(keycode)
|
38
65
|
@supported_code ||= {}
|
39
|
-
@supported_code[
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
66
|
+
@supported_code[keycode] ||= if @device.support?(keycode)
|
67
|
+
true
|
68
|
+
else
|
69
|
+
search_candidates(keycode: keycode)
|
70
|
+
exit(1)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def search_candidates(keycode:)
|
75
|
+
candidates = search_codes(keycode: keycode)
|
76
|
+
|
77
|
+
warn "Did you mean? #{candidates.join(' / ')}" unless candidates.empty?
|
78
|
+
warn "sendkey: #{remove_prefix(keycode)} is unsupported."
|
79
|
+
end
|
80
|
+
|
81
|
+
def search_codes(keycode: nil)
|
82
|
+
query = keycode&.upcase&.gsub('KEY_', '')
|
83
|
+
LinuxInput.constants
|
84
|
+
.select { |c| c[/KEY_.*#{query}.*/] }
|
85
|
+
.select { |c| @device.support?(c) }
|
86
|
+
.map { |c| c.to_s.gsub('KEY_', '') }
|
87
|
+
end
|
88
|
+
|
89
|
+
def keycode_const(keycode)
|
90
|
+
Object.const_get "LinuxInput::#{keycode}"
|
91
|
+
end
|
92
|
+
|
93
|
+
def clear_modifiers
|
94
|
+
modifiers = %w[ CAPSLOCK LEFTALT LEFTCTRL LEFTMETA
|
95
|
+
LEFTSHIFT RIGHTALT RIGHTCTRL RIGHTSHIFT ]
|
96
|
+
modifiers.each { |code| key_event(keycode: key_prefix(code), press: false) }
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def split_param(param)
|
102
|
+
param.split('+').map { |code| key_prefix(code) }
|
103
|
+
end
|
104
|
+
|
105
|
+
def key_prefix(code)
|
106
|
+
"KEY_#{code.upcase}"
|
46
107
|
end
|
47
108
|
|
48
|
-
def
|
49
|
-
|
109
|
+
def remove_prefix(keycode)
|
110
|
+
keycode.gsub('KEY_', '')
|
50
111
|
end
|
51
112
|
end
|
52
113
|
end
|
metadata
CHANGED
@@ -1,43 +1,57 @@
|
|
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.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- iberianpig
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-03-
|
11
|
+
date: 2020-03-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: evdev
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
19
|
+
version: '1.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
26
|
+
version: '1.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: fusuma
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.5
|
33
|
+
version: '1.5'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.5'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: linux_input
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.1'
|
34
48
|
type: :runtime
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version: 1.
|
54
|
+
version: '1.1'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: bundler
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -224,7 +238,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
224
238
|
- !ruby/object:Gem::Version
|
225
239
|
version: '0'
|
226
240
|
requirements: []
|
227
|
-
rubygems_version: 3.0.
|
241
|
+
rubygems_version: 3.0.3
|
228
242
|
signing_key:
|
229
243
|
specification_version: 4
|
230
244
|
summary: Fusuma plugin that sending virtual keyboard events
|