fusuma-plugin-sendkey 0.1.1 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3087cd15e356a48d1f8fd2398daed7f6153d4e9c005db98ffad34627b357bc65
4
- data.tar.gz: 0dd9da2ff1ef200d76691f9a3e72fe8efff68cea8e6eef1c448387df6154daf1
3
+ metadata.gz: e1f133065105c5e8bcdc9dd04873d6245cb3b6357a1a9f45a437cd0150b5a959
4
+ data.tar.gz: c6f759e41f007688902c837f1fedc65e00d70ee3a41bb8bc9baf28de48e3c8ed
5
5
  SHA512:
6
- metadata.gz: 830a41f20bfa018ceff548a8c660012947657fbd18b8e369a1033fb4f4d0e2f665ade047eeafa9d3ba3ade8ba5079a1c1044cc6401b4222da20847bced619a7b
7
- data.tar.gz: 9f8ae60d5377799ed80844ba3a218049c1a736cf7ed0e733dea347067a30fc548f6aa5c82b2311858e2474f8ad0d1df8a3e8739730d9e301664a784d2a073b26
6
+ metadata.gz: 6390589b886bc137bed6e4bbd4cab68b890d7660fbf09462aa471557c8c7533cff11f73cec2f25ce3875489ef3abd44e82999af2f400dbe619470f29e4d2e17b
7
+ data.tar.gz: 4f80040d29ff16b5184e2f2f51485e39e178a029da0aec8e2c647da9428bd08ab54f5814c49194eeccdfac012091e4235392768d02de71191fff8af3b9bf4f4f
data/.gitignore CHANGED
@@ -10,3 +10,4 @@
10
10
 
11
11
  # rspec failure tracking
12
12
  .rspec_status
13
+ .ruby-version
@@ -11,3 +11,10 @@ Metrics/LineLength:
11
11
  Max: 100
12
12
  Exclude:
13
13
  - "fusuma-plugin-*.gemspec"
14
+
15
+ Style/HashEachMethods:
16
+ Enabled: true
17
+ Style/HashTransformKeys:
18
+ Enabled: true
19
+ Style/HashTransformValues:
20
+ Enabled: true
@@ -6,4 +6,4 @@ rvm:
6
6
  - 2.6.1
7
7
  before_install:
8
8
  - gem install bundler -v 2.0.1
9
- - sudo apt-get -y install evemu-tools libevdev-dev
9
+ - sudo apt-get -y install libevdev-dev
@@ -0,0 +1,21 @@
1
+ # Changelog
2
+
3
+ ## [Unreleased](https://github.com/iberianpig/fusuma-plugin-keypress/tree/HEAD)
4
+
5
+ [Full Changelog](https://github.com/iberianpig/fusuma-plugin-keypress/compare/v0.1.1...HEAD)
6
+
7
+ **Closed issues:**
8
+
9
+ - Trigger a command multiple times while keeping the key pressed [\#1](https://github.com/iberianpig/fusuma-plugin-keypress/issues/1)
10
+
11
+ ## [v0.1.1](https://github.com/iberianpig/fusuma-plugin-keypress/tree/v0.1.1) (2020-02-18)
12
+
13
+ [Full Changelog](https://github.com/iberianpig/fusuma-plugin-keypress/compare/v0.1.0...v0.1.1)
14
+
15
+ ## [v0.1.0](https://github.com/iberianpig/fusuma-plugin-keypress/tree/v0.1.0) (2019-11-12)
16
+
17
+ [Full Changelog](https://github.com/iberianpig/fusuma-plugin-keypress/compare/fb8d8ccfc3828e487607706335f670ae5392f08d...v0.1.0)
18
+
19
+
20
+
21
+ \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # Fusuma::Plugin::Sendkey [![Gem Version](https://badge.fury.io/rb/fusuma-plugin-sendkey.svg)](https://badge.fury.io/rb/fusuma-plugin-sendkey) [![Build Status](https://travis-ci.com/iberianpig/fusuma-plugin-sendkey.svg?branch=master)](https://travis-ci.com/iberianpig/fusuma-plugin-sendkey)
2
2
 
3
- [Fusuma](https://github.com/iberianpig/fusuma) plugin that sending virtual keyboard events
3
+ [Fusuma](https://github.com/iberianpig/fusuma) plugin to send keyboard events
4
4
 
5
- * Emulate keyboard events with evemu-event
6
- * This plugin replaces xdotool
5
+ * Low-latency key event emulation with evdev
6
+ * Alternative to xdotool available for X11 and Wayland
7
7
 
8
8
  ## Installation
9
9
 
@@ -11,33 +11,45 @@ Run the following code in your terminal.
11
11
 
12
12
  ### Install dependencies
13
13
 
14
+ **NOTE: If you have installed ruby by apt, you must install ruby-dev.**
14
15
  ```sh
15
- $ sudo apt-get install evemu-tools libevdev-dev
16
+ $ sudo apt-get install libevdev-dev ruby-dev
16
17
  ```
17
18
 
18
19
  ### Install fusuma-plugin-sendkey
19
20
 
20
21
  ```sh
21
- $ gem install fusuma-plugin-sendkey
22
+ $ sudo gem install fusuma-plugin-sendkey
22
23
  ```
23
24
 
24
25
 
25
- ## List avaiable keys
26
+ ## List available keys
26
27
 
27
28
  ```sh
28
29
  $ fusuma-sendkey -l
29
30
  ```
31
+ If you want to look up a specific key, like the next song or the previous song, the `grep -i` refinement search is useful.
32
+
33
+ ```sh
34
+ $ fusuma-sendkey -l | grep -i song
35
+ NEXTSONG
36
+ PREVIOUSSONG
37
+ ```
30
38
 
31
39
  ## Run fusuma-sendkey on Terminal
32
40
 
33
- * `fusuma-sendkey` can emulate keyboard inputs as a command
34
- * Combine keys for pressing the same time with `+`
41
+ * `fusuma-sendkey` command is available on your terminal
42
+ * `fusuma-sendkey` supports modifier keys and multiple key presses.
43
+ Combine keys for pressing the same time with `+`
35
44
 
36
45
 
37
46
  ```sh
38
- $ fusuma-sendkey LEFTCTRL+T
47
+ $ fusuma-sendkey LEFTCTRL+T # press ctrl key + t key
39
48
  ```
40
49
 
50
+ Some of the keys found with `fusuma-sendkey -l` may actually be invalid keys.
51
+ So test it once with `fusuma-sendkey <KEYCODE>` and then add it to config.yml.
52
+
41
53
 
42
54
  ## Add sendkey properties to config.yml
43
55
 
@@ -58,6 +70,26 @@ swipe:
58
70
  sendkey: "LEFTCTRL+W" # close tab
59
71
  ```
60
72
 
73
+
74
+ ### Specify keyboard by device name
75
+
76
+ If you got following error message, try to set your keyboard name to `plugin.executors.sendkey_executor.device_name` on config.yml
77
+
78
+ ```shell
79
+ $ fusuma-sendkey -l
80
+ sendkey: Keyboard: /keyboard|Keyboard|KEYBOARD/ is not found
81
+ ```
82
+
83
+ Set the following options to recognize keyboard only for the specified keyboard device.
84
+ Open `~/.config/fusuma/config.yml` and add the following code at the bottom.
85
+
86
+ ```yaml
87
+ plugin:
88
+ executors:
89
+ sendkey_executor:
90
+ device_name: 'YOUR KEYBOARD NAME'
91
+ ```
92
+
61
93
  ## Contributing
62
94
 
63
95
  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/Rakefile CHANGED
@@ -1,6 +1,15 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ task default: :spec
9
+
10
+ require 'github_changelog_generator/task'
11
+
12
+ GitHubChangelogGenerator::RakeTask.new :changelog do |config|
13
+ config.user = 'iberianpig'
14
+ config.project = 'fusuma-plugin-keypress'
15
+ end
@@ -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
@@ -3,6 +3,7 @@
3
3
 
4
4
  require 'optparse'
5
5
  require_relative '../lib/fusuma/plugin/sendkey/keyboard.rb'
6
+ require_relative '../lib/fusuma/plugin/sendkey/version.rb'
6
7
 
7
8
  option = {}
8
9
  opt = OptionParser.new
@@ -19,7 +20,7 @@ end
19
20
  opt.parse!(ARGV)
20
21
 
21
22
  if option[:list]
22
- puts Keyboard.new.available_codes
23
+ puts Fusuma::Plugin::Sendkey::Keyboard.new(name_pattern: nil).search_codes
23
24
  return
24
25
  end
25
26
 
@@ -36,6 +37,5 @@ if param.nil?
36
37
  exit 1
37
38
  end
38
39
 
39
- Keyboard.new.type_command(param: param).tap do |command|
40
- exec(command)
41
- end
40
+ keyboard = Fusuma::Plugin::Sendkey::Keyboard.new
41
+ keyboard.valid?(param: param) && keyboard.type(param: param)
@@ -10,8 +10,8 @@ Gem::Specification.new do |spec|
10
10
  spec.authors = ['iberianpig']
11
11
  spec.email = ['yhkyky@gmail.com']
12
12
 
13
- spec.summary = 'Fusuma plugin that sending virtual keyboard events'
14
- spec.description = 'Fusuma::Plugin::Sendkey emulate keyboard events with evemu-event'
13
+ spec.summary = 'Fusuma plugin to send keyboard events'
14
+ spec.description = 'Fusuma::Plugin::Sendkey emulate keyboard events with evdev'
15
15
  spec.homepage = 'https://github.com/iberianpig/fusuma-plugin-sendkey'
16
16
  spec.license = 'MIT'
17
17
 
@@ -24,8 +24,8 @@ 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 'fusuma', '~> 1.7'
28
+ spec.add_dependency 'revdev'
29
29
 
30
30
  spec.add_development_dependency 'bundler'
31
31
  spec.add_development_dependency 'github_changelog_generator', '~> 1.14'
@@ -9,7 +9,7 @@ module Fusuma
9
9
  class SendkeyExecutor < Executor
10
10
  def config_param_types
11
11
  {
12
- 'device_path': String
12
+ 'device_name': String
13
13
  }
14
14
  end
15
15
 
@@ -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
- device = Sendkey::Device.new(path: config_params(:device_path))
46
- Sendkey::Keyboard.new(device: device)
42
+ name_pattren = config_params(:device_name)
43
+ Sendkey::Keyboard.new(name_pattern: name_pattren)
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)
@@ -1,62 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'evdev'
4
-
5
3
  module Fusuma
6
4
  module Plugin
7
5
  module Sendkey
8
6
  # handle Evdev device
9
7
  class Device
10
- attr_reader :device_id
11
- def initialize(path: nil)
12
- return if path && (@evdev = Evdev.new(path))
13
-
14
- (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
22
- end
8
+ def initialize(path:)
9
+ @evdev = Revdev::EventDevice.new(path)
23
10
  end
24
11
 
25
12
  def path
26
- raise 'Keyboard is not found' if @evdev.nil?
13
+ raise 'Device path is not found' if @evdev.nil?
27
14
 
28
15
  @path ||= @evdev.file.path
29
16
  end
30
17
 
31
- def support?(code)
32
- keycode = convert_keycode(code)
33
- @evdev.supports_event?(keycode)
34
- rescue NameError
35
- candidates = search_codes(code: code)
36
-
37
- warn "Did you mean? #{candidates.join(' / ')}" unless candidates.empty?
38
-
39
- false
40
- 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}"
18
+ def write_event(event)
19
+ @evdev.write_input_event(event)
60
20
  end
61
21
  end
62
22
  end
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'revdev'
4
+ require 'fusuma/device'
5
+
3
6
  require_relative './device.rb'
4
7
 
5
8
  module Fusuma
@@ -7,46 +10,116 @@ module Fusuma
7
10
  module Sendkey
8
11
  # Emulate Keyboard
9
12
  class Keyboard
10
- def initialize(device: nil)
11
- @device = device || Device.new
13
+ def initialize(name_pattern: 'keyboard|Keyboard|KEYBOARD')
14
+ device = find_device(name_pattern: name_pattern)
15
+
16
+ if device.nil?
17
+ warn "sendkey: Keyboard: /#{name_pattern}/ is not found"
18
+ exit(1)
19
+ end
20
+
21
+ @device = Device.new(path: "/dev/input/#{device.id}")
12
22
  end
13
23
 
24
+ attr_reader :device
25
+
14
26
  # @param param [String]
15
- def type_command(param:)
27
+ def type(param:)
16
28
  return unless param.is_a?(String)
17
29
 
18
- codes = param.split('+')
19
- press_commands = codes.map { |code| press_command(code) }
20
- release_commands = codes.reverse.map { |code| release_command(code) }
30
+ keycodes = split_param(param)
21
31
 
22
- (press_commands | release_commands).join(' && ')
32
+ clear_modifiers
33
+ keycodes.each { |keycode| key_event(keycode: keycode, press: true) }
34
+ key_sync(press: true)
35
+ keycodes.reverse.map { |keycode| key_event(keycode: keycode, press: false) }
36
+ key_sync(press: false)
23
37
  end
24
38
 
25
- def press_command(code)
26
- return unless support?(code)
39
+ # @param param [String]
40
+ def valid?(param:)
41
+ return unless param.is_a?(String)
27
42
 
28
- @device.emulate(code: code, press: true)
43
+ keycodes = split_param(param)
44
+ keycodes.all? { |keycode| support?(keycode) }
29
45
  end
30
46
 
31
- def release_command(code)
32
- return unless support?(code)
47
+ def key_event(keycode:, press: true)
48
+ event = Revdev::InputEvent.new(
49
+ nil,
50
+ Revdev.const_get(:EV_KEY),
51
+ Revdev.const_get(keycode),
52
+ press ? 1 : 0
53
+ )
54
+ @device.write_event(event)
55
+ end
33
56
 
34
- @device.emulate(code: code, press: false)
57
+ def key_sync(press: true)
58
+ event = Revdev::InputEvent.new(
59
+ nil,
60
+ Revdev.const_get(:EV_SYN),
61
+ Revdev.const_get(:SYN_REPORT),
62
+ press ? 1 : 0
63
+ )
64
+ @device.write_event(event)
35
65
  end
36
66
 
37
- def support?(code)
67
+ def support?(keycode)
38
68
  @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
69
+ @supported_code[keycode] ||= if find_code(keycode: keycode)
70
+ true
71
+ else
72
+ search_candidates(keycode: keycode)
73
+ end
74
+ end
75
+
76
+ def search_candidates(keycode:)
77
+ query = keycode&.upcase&.gsub('KEY_', '')
78
+
79
+ candidates = search_codes(query: query)
80
+
81
+ warn "Did you mean? #{candidates.join(' / ')}" unless candidates.empty?
82
+ warn "sendkey: #{remove_prefix(keycode)} is unsupported."
83
+ end
84
+
85
+ def search_codes(query: nil)
86
+ Revdev.constants
87
+ .select { |c| c[/KEY_.*#{query}.*/] }
88
+ .map { |c| c.to_s.gsub('KEY_', '') }
89
+ end
90
+
91
+ def find_code(keycode: nil)
92
+ query = keycode&.upcase&.gsub('KEY_', '')
93
+
94
+ Revdev.constants.find { |c| c == "KEY_#{query}".to_sym }
95
+ end
96
+
97
+ def keycode_const(keycode)
98
+ Object.const_get "LinuxInput::#{keycode}"
99
+ end
100
+
101
+ def clear_modifiers
102
+ modifiers = %w[ CAPSLOCK LEFTALT LEFTCTRL LEFTMETA
103
+ LEFTSHIFT RIGHTALT RIGHTCTRL RIGHTSHIFT ]
104
+ modifiers.each { |code| key_event(keycode: key_prefix(code), press: false) }
105
+ end
106
+
107
+ private
108
+
109
+ def find_device(name_pattern:)
110
+ Fusuma::Device.all.find { |d| d.name.match(/#{name_pattern}/) }
111
+ end
112
+
113
+ def split_param(param)
114
+ param.split('+').map { |code| key_prefix(code) }
115
+ end
116
+
117
+ def key_prefix(code)
118
+ "KEY_#{code.upcase}"
46
119
  end
47
120
 
48
- def available_codes
49
- @device.search_codes
121
+ def remove_prefix(keycode)
122
+ keycode.gsub('KEY_', '')
50
123
  end
51
124
  end
52
125
  end
@@ -3,7 +3,7 @@
3
3
  module Fusuma
4
4
  module Plugin
5
5
  module Sendkey
6
- VERSION = '0.1.1'
6
+ VERSION = '0.5.0'
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fusuma-plugin-sendkey
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.5.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-03 00:00:00.000000000 Z
11
+ date: 2020-07-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: evdev
14
+ name: fusuma
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '1.7'
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.7'
27
27
  - !ruby/object:Gem::Dependency
28
- name: fusuma
28
+ name: revdev
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: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 1.5.0
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -178,7 +178,7 @@ dependencies:
178
178
  - - ">="
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
- description: Fusuma::Plugin::Sendkey emulate keyboard events with evemu-event
181
+ description: Fusuma::Plugin::Sendkey emulate keyboard events with evdev
182
182
  email:
183
183
  - yhkyky@gmail.com
184
184
  executables:
@@ -190,6 +190,7 @@ files:
190
190
  - ".rspec"
191
191
  - ".rubocop.yml"
192
192
  - ".travis.yml"
193
+ - CHANGELOG.md
193
194
  - CODE_OF_CONDUCT.md
194
195
  - Gemfile
195
196
  - LICENSE.txt
@@ -226,5 +227,5 @@ requirements: []
226
227
  rubygems_version: 3.0.3
227
228
  signing_key:
228
229
  specification_version: 4
229
- summary: Fusuma plugin that sending virtual keyboard events
230
+ summary: Fusuma plugin to send keyboard events
230
231
  test_files: []