fusuma-plugin-sendkey 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 37cb58747c750acf4c991fd174a8e19182336f518a54f4b2c816e3ead7f628eb
4
- data.tar.gz: 9309dd43e32c3cd8b6791fe6c1a56f439fff6d7a05af41f9654e96360efd76bd
3
+ metadata.gz: d27660bea09b33620ab905e3b112cf0f9884b3617097daadd6d8ca03d2d5c14b
4
+ data.tar.gz: 70b1f7ddffaa8d874a44feaec361c60d0bca6744f30ec6a5c6f3c3efb1fe2a9f
5
5
  SHA512:
6
- metadata.gz: 9f93e2a400820e3b4e138da96e71f90067bf514d35751bc6f31f6d58d9d4bc72ec18e621f04ede71eaa26131bbede74b7fb8bda420e8c38e3895f78299169616
7
- data.tar.gz: 934f126d52d893d577fa9b5cec25209a88fbb3298d0004238e004676a898ced197ff481bed6aa1e3015fb55a05d33762aac9823b4a10d3bc796a940dc5e28ffc
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
- * Emulate keyboard events with evemu-event
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 evemu-tools libevdev-dev ruby-ffi
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 avaiable keys
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` can emulate keyboard inputs as a command
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
- # require "pry"
11
- # Pry.start
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.available_codes
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.type_command(param: param).tap do |command|
41
- exec(command)
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.0'
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
- exec(search_command(event))
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
- search_command(event)
35
+ keyboard.valid?(param: search_param(event))
38
36
  end
39
37
 
40
- # @param event [Event]
41
- # @return [String]
42
- # @return [NilClass]
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
- begin
16
- evdev = Evdev.new("/dev/input/event#{i}")
17
- @evdev = evdev if evdev.supports_event?(convert_keycode('LEFTALT'))
18
- rescue Errno::ENOENT # No such file or directory
19
- false
20
- # TODO: rescue Errno::EACCES
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?(code)
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 type_command(param:)
17
+ def type(param:)
16
18
  return unless param.is_a?(String)
17
19
 
18
- codes = param.split('+')
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
- (press_commands | release_commands).join(' && ')
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
- def press_command(code)
26
- return unless support?(code)
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.emulate(code: code, press: true)
41
+ @device_file = File.open(@device.path, Fcntl::O_WRONLY | Fcntl::O_NDELAY)
29
42
  end
30
43
 
31
- def release_command(code)
32
- return unless support?(code)
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
- @device.emulate(code: code, press: false)
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?(code)
64
+ def support?(keycode)
38
65
  @supported_code ||= {}
39
- @supported_code[code] ||= if @device.support?(code)
40
- true
41
- else
42
- warn "sendkey: #{code} is unsupported."
43
- warn 'Please check your config.yml.'
44
- exit 1
45
- end
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 available_codes
49
- @device.search_codes
109
+ def remove_prefix(keycode)
110
+ keycode.gsub('KEY_', '')
50
111
  end
51
112
  end
52
113
  end
@@ -3,7 +3,7 @@
3
3
  module Fusuma
4
4
  module Plugin
5
5
  module Sendkey
6
- VERSION = '0.2.1'
6
+ VERSION = '0.3.0'
7
7
  end
8
8
  end
9
9
  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.2.1
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-04 00:00:00.000000000 Z
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.0
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.5.0
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.6
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