touchscreen-taps 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +49 -0
- data/Rakefile +4 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/exe/touchscreen-taps +6 -0
- data/lib/touchscreen_taps.rb +36 -0
- data/lib/touchscreen_taps/config.rb +43 -0
- data/lib/touchscreen_taps/default_config.yml +5 -0
- data/lib/touchscreen_taps/event.rb +20 -0
- data/lib/touchscreen_taps/event_filter.rb +14 -0
- data/lib/touchscreen_taps/event_parser.rb +33 -0
- data/lib/touchscreen_taps/executor.rb +31 -0
- data/lib/touchscreen_taps/gesture_buffer.rb +83 -0
- data/lib/touchscreen_taps/libinput.rb +36 -0
- data/lib/touchscreen_taps/tap_and_hold_detector.rb +50 -0
- data/lib/touchscreen_taps/touchscreen_device.rb +35 -0
- data/lib/touchscreen_taps/version.rb +5 -0
- data/touchscreen-taps.gemspec +29 -0
- metadata +68 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: cd4ca10f5439c6236d2e179e46f19d63531fd59d7b89ad94d421817952b0a0c6
|
4
|
+
data.tar.gz: 91ac28937e62700d68e407384a62dba6b4adcd344345b083d7cbcef9f4a09238
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 286e7df3bf4c5c21a17adb9e912ff2ffc3c648094b6eb83bfd5646952e9edd3b83dc41bbcd7a300c22990c40ff4227f53973d6de114afd3b9559447f0655dd27
|
7
|
+
data.tar.gz: 2beede4c0d9a0e9eafef326fada7d799ad069ee76e3c5d7ff7d3d42ba539d1c3df79a2013a6da832260708522d1cb293f4bd4d70a01c9c1aa09ea43a05ec2c01
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2020 Anton Sokolskyi
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# TouchscreenTaps
|
2
|
+
|
3
|
+
TouchscreenTaps is a touchscreen taps recognizer. It allows "tap and hold" gesture to be recognized and assign a command to it.
|
4
|
+
|
5
|
+
# Instalation
|
6
|
+
|
7
|
+
```bash
|
8
|
+
sudo gpasswd -a $USER input
|
9
|
+
sudo apt install libinput-tools
|
10
|
+
sudo apt install xdotool
|
11
|
+
sudo apt install ruby
|
12
|
+
sudo gem install touchscreen-taps
|
13
|
+
```
|
14
|
+
|
15
|
+
# Usage
|
16
|
+
```bash
|
17
|
+
touchscreen-taps
|
18
|
+
```
|
19
|
+
Pass custom config
|
20
|
+
```bash
|
21
|
+
touchscreen-taps /home/user/custom_config.yml
|
22
|
+
```
|
23
|
+
|
24
|
+
# Config example
|
25
|
+
```yaml
|
26
|
+
---
|
27
|
+
tap_and_hold: # event name
|
28
|
+
1: # fingers count
|
29
|
+
command: 'xdotool click 3'
|
30
|
+
acceptance_delay: '0.5' # seconds
|
31
|
+
```
|
32
|
+
# Run as daemon
|
33
|
+
```bash
|
34
|
+
touchscreen-taps &
|
35
|
+
```
|
36
|
+
|
37
|
+
# Autostart
|
38
|
+
```bash
|
39
|
+
echo 'touchscreen-taps &' | sudo tee /etc/profile.d/start-touchscreen-taps.sh
|
40
|
+
```
|
41
|
+
|
42
|
+
# Tested on:
|
43
|
+
Surface Pro 3 (i5/8gb/256gb)
|
44
|
+
Ubuntu 18.04 LTS (linux 5.5, Gnome, Xorg)
|
45
|
+
|
46
|
+
|
47
|
+
## License
|
48
|
+
|
49
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'touchscreen_taps'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'irb'
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'touchscreen_taps/libinput'
|
4
|
+
require_relative 'touchscreen_taps/touchscreen_device'
|
5
|
+
require_relative 'touchscreen_taps/gesture_buffer'
|
6
|
+
require_relative 'touchscreen_taps/config'
|
7
|
+
require_relative 'touchscreen_taps/event'
|
8
|
+
require_relative 'touchscreen_taps/event_filter'
|
9
|
+
require_relative 'touchscreen_taps/event_parser'
|
10
|
+
require_relative 'touchscreen_taps/tap_and_hold_detector'
|
11
|
+
require_relative 'touchscreen_taps/executor'
|
12
|
+
|
13
|
+
module TouchscreenTaps
|
14
|
+
# Main runner
|
15
|
+
class Runner
|
16
|
+
def initialize(config_path)
|
17
|
+
config = Config.new(config_path)
|
18
|
+
@buffer = config.buffer
|
19
|
+
@touchscreen = config.touchscreen
|
20
|
+
@detector = TapAndHoldDetector.new(config)
|
21
|
+
@executor = Executor.new(config)
|
22
|
+
end
|
23
|
+
|
24
|
+
def process_events
|
25
|
+
Libinput.events(@touchscreen) do |event|
|
26
|
+
event = EventFilter.call(event)
|
27
|
+
next unless event
|
28
|
+
|
29
|
+
event = EventParser.call(event)
|
30
|
+
@buffer.push(event)
|
31
|
+
command = @detector.process(@buffer)
|
32
|
+
@executor.run(command)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TouchscreenTaps
|
4
|
+
# Holds main configurations
|
5
|
+
class Config
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
attr_reader :buffer
|
9
|
+
attr_reader :touchscreen
|
10
|
+
|
11
|
+
def initialize(path = nil)
|
12
|
+
@buffer = fetch_buffer
|
13
|
+
@touchscreen = fetch_touchscreen
|
14
|
+
@config = fetch_config(path)
|
15
|
+
end
|
16
|
+
|
17
|
+
def by_keys(keys)
|
18
|
+
@config.dig(*keys)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def fetch_buffer
|
24
|
+
GestureBuffer.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def fetch_touchscreen
|
28
|
+
devices = Libinput.devices
|
29
|
+
touchscreens = TouchscreenDevice.select_from(devices)
|
30
|
+
# touchscreen can be nil
|
31
|
+
# in that case events from all touch-capable devices will be processed
|
32
|
+
touchscreens.count == 1 ? touchscreens.first : nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def fetch_config(path)
|
36
|
+
YAML.load_file(path || default_config_path)
|
37
|
+
end
|
38
|
+
|
39
|
+
def default_config_path
|
40
|
+
"#{__dir__}/default_config.yml"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TouchscreenTaps
|
4
|
+
# Parsed Event object
|
5
|
+
class Event
|
6
|
+
attr_reader :timestamp
|
7
|
+
attr_reader :type
|
8
|
+
attr_reader :finger
|
9
|
+
attr_reader :move_x
|
10
|
+
attr_reader :move_y
|
11
|
+
|
12
|
+
def initialize(type, finger, move_x = nil, move_y = nil)
|
13
|
+
@type = type
|
14
|
+
@finger = finger
|
15
|
+
@move_x = move_x
|
16
|
+
@move_y = move_y
|
17
|
+
@timestamp = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TouchscreenTaps
|
4
|
+
# Parses a raw line and creates an event object
|
5
|
+
class EventParser
|
6
|
+
class << self
|
7
|
+
def call(event)
|
8
|
+
_device, event_name, _time, text = event.strip.split(nil, 4)
|
9
|
+
Event.new(type(event_name), finger(text), *direction(text))
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def direction(text)
|
15
|
+
return if text.nil?
|
16
|
+
|
17
|
+
_finger, _finger2, x, y = text.tr('/|(|)', ' ').split
|
18
|
+
[x, y]
|
19
|
+
end
|
20
|
+
|
21
|
+
def type(text)
|
22
|
+
text.split('_').last
|
23
|
+
end
|
24
|
+
|
25
|
+
def finger(text)
|
26
|
+
return if text.nil?
|
27
|
+
|
28
|
+
count, = text.split(nil, 3)
|
29
|
+
count.to_i + 1
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TouchscreenTaps
|
4
|
+
# Executes commands from config file
|
5
|
+
class Executor
|
6
|
+
def initialize(config)
|
7
|
+
@config = config
|
8
|
+
end
|
9
|
+
|
10
|
+
def run(cmd)
|
11
|
+
return if cmd.nil?
|
12
|
+
|
13
|
+
command = @config.by_keys(command_to_keys(cmd)).fetch('command')
|
14
|
+
execute(command) if command
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def execute(command)
|
20
|
+
puts "Executing '#{command}'"
|
21
|
+
fork do
|
22
|
+
Process.daemon(true)
|
23
|
+
exec(command)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def command_to_keys(cmd)
|
28
|
+
[cmd[:name], cmd[:fingers]]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TouchscreenTaps
|
4
|
+
# Buffer for all events related to a single gesture
|
5
|
+
# Gesture is considered started when first finger touches the screen
|
6
|
+
# Gesture is considired ended when last finger leaves the screen
|
7
|
+
# Between start and end points at least one finger
|
8
|
+
# should be touching the screen
|
9
|
+
class GestureBuffer
|
10
|
+
TIME_TO_KEEP = 3 # seconds
|
11
|
+
UP_TYPE = 'UP'
|
12
|
+
DOWN_TYPE = 'DOWN'
|
13
|
+
MOTION_TYPE = 'MOTION'
|
14
|
+
attr_reader :events
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@events = []
|
18
|
+
end
|
19
|
+
|
20
|
+
def push(event)
|
21
|
+
delete_old_events
|
22
|
+
clear unless gesture_in_progress?
|
23
|
+
remove_previous_events(event) if repeating_touch?(event)
|
24
|
+
|
25
|
+
@events.push(event)
|
26
|
+
end
|
27
|
+
|
28
|
+
def empty?
|
29
|
+
@events.empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
def gesture_in_progress?
|
33
|
+
down_touches.count > up_touches.count
|
34
|
+
end
|
35
|
+
|
36
|
+
def down_touches
|
37
|
+
events_by_type(DOWN_TYPE)
|
38
|
+
end
|
39
|
+
|
40
|
+
def up_touches
|
41
|
+
events_by_type(UP_TYPE)
|
42
|
+
end
|
43
|
+
|
44
|
+
def motion_touches
|
45
|
+
events_by_type(MOTION_TYPE)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def delete_old_events
|
51
|
+
@events.each do |event|
|
52
|
+
next if (current_time - event.timestamp) < TIME_TO_KEEP
|
53
|
+
|
54
|
+
@events.delete(event)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def clear
|
59
|
+
@events.clear
|
60
|
+
end
|
61
|
+
|
62
|
+
def current_time
|
63
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
64
|
+
end
|
65
|
+
|
66
|
+
def repeating_touch?(event)
|
67
|
+
return false unless event.type == DOWN_TYPE
|
68
|
+
|
69
|
+
!@events.find { |e| e.finger == event.finger }.nil?
|
70
|
+
end
|
71
|
+
|
72
|
+
def remove_previous_events(event)
|
73
|
+
@events.select { |e| e.finger == event.finger }.each do |e|
|
74
|
+
@events.delete(e)
|
75
|
+
end
|
76
|
+
@events.delete(@events.find { |e| e.type == UP_TYPE })
|
77
|
+
end
|
78
|
+
|
79
|
+
def events_by_type(type)
|
80
|
+
@events.select { |e| e.type == type }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TouchscreenTaps
|
4
|
+
# libinput wrapper
|
5
|
+
# makes debug_events available in ruby
|
6
|
+
class Libinput
|
7
|
+
require 'open3'
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def events(device = nil)
|
11
|
+
Open3.popen3(debug_events_cmd(device)) do |_in, out, _err, _wait_thr|
|
12
|
+
out.each do |event|
|
13
|
+
yield(event.chomp)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def devices
|
19
|
+
Open3.popen3(list_devices_cmd) do |_in, out, _err, _wait_thr|
|
20
|
+
out.read.split("\n\n").map { |d| d.split("\n") }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def debug_events_cmd(device)
|
27
|
+
'stdbuf -oL -- libinput debug-events' \
|
28
|
+
"#{' --device=' + device.kernel unless device.nil?}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def list_devices_cmd
|
32
|
+
'libinput list-devices'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TouchscreenTaps
|
4
|
+
# Detects tap-and-hold gesture
|
5
|
+
class TapAndHoldDetector
|
6
|
+
COMMAND_TYPE = 'tap_and_hold'
|
7
|
+
|
8
|
+
def initialize(config)
|
9
|
+
@config = config
|
10
|
+
end
|
11
|
+
|
12
|
+
def process(buffer)
|
13
|
+
return if return_conditions_met?(buffer)
|
14
|
+
|
15
|
+
down_touches = buffer.down_touches
|
16
|
+
up_touches = buffer.up_touches
|
17
|
+
|
18
|
+
last_down_touch = down_touches.max_by(&:timestamp)
|
19
|
+
last_up_touch = up_touches.max_by(&:timestamp)
|
20
|
+
|
21
|
+
if hold_enough?(last_up_touch, last_down_touch)
|
22
|
+
return { name: COMMAND_TYPE, fingers: down_touches.count }
|
23
|
+
end
|
24
|
+
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def hold_enough?(up_touch, down_touch)
|
31
|
+
return false if up_touch.nil? || down_touch.nil?
|
32
|
+
|
33
|
+
required_delay = acceptance_delay(down_touch)
|
34
|
+
return false if required_delay.nil?
|
35
|
+
|
36
|
+
up_touch.timestamp - down_touch.timestamp > required_delay.to_f
|
37
|
+
end
|
38
|
+
|
39
|
+
def return_conditions_met?(buffer)
|
40
|
+
buffer.empty? ||
|
41
|
+
buffer.gesture_in_progress? ||
|
42
|
+
buffer.motion_touches.any?
|
43
|
+
end
|
44
|
+
|
45
|
+
def acceptance_delay(down_touch)
|
46
|
+
@config.by_keys([COMMAND_TYPE, down_touch.finger])
|
47
|
+
&.fetch('acceptance_delay')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TouchscreenTaps
|
4
|
+
# represents a physical input device (e.g touchscreen)
|
5
|
+
class TouchscreenDevice
|
6
|
+
REQUIRED_CAPABILITY = 'touch'
|
7
|
+
attr_reader :kernel
|
8
|
+
|
9
|
+
def initialize(kernel)
|
10
|
+
@kernel = kernel
|
11
|
+
end
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def select_from(devices)
|
15
|
+
devices.map do |device|
|
16
|
+
next unless capable?(device)
|
17
|
+
|
18
|
+
kernel = kernel_path(device)
|
19
|
+
new(kernel) unless kernel.nil?
|
20
|
+
end.compact
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def capable?(device)
|
26
|
+
device.find { |f| f =~ /^Capabilities:/ }
|
27
|
+
.include?(REQUIRED_CAPABILITY)
|
28
|
+
end
|
29
|
+
|
30
|
+
def kernel_path(device)
|
31
|
+
device.find { |f| f =~ /^Kernel:/ }.split(' ').last
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/touchscreen_taps/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'touchscreen-taps'
|
7
|
+
spec.version = TouchscreenTaps::VERSION
|
8
|
+
spec.authors = ['Anton Sokolskyi']
|
9
|
+
spec.email = ['antonsokolskyi@gmail.com']
|
10
|
+
|
11
|
+
spec.summary = 'Touchscreen taps recognizer'
|
12
|
+
spec.description = 'Allows to recognize tap-and-hold gesture'
|
13
|
+
spec.homepage = 'https://github.com/antonsokolskyy/touchscreen-taps'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
|
16
|
+
|
17
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
18
|
+
spec.metadata['source_code_uri'] = 'https://github.com/antonsokolskyy/touchscreen-taps'
|
19
|
+
spec.metadata['changelog_uri'] = 'https://github.com/antonsokolskyy/touchscreen-taps/blob/master/CHANGELOG.md'
|
20
|
+
|
21
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
22
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
23
|
+
f.match(%r{^(test|spec|features)/})
|
24
|
+
end
|
25
|
+
end
|
26
|
+
spec.bindir = 'exe'
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ['lib']
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: touchscreen-taps
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Anton Sokolskyi
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-02-21 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Allows to recognize tap-and-hold gesture
|
14
|
+
email:
|
15
|
+
- antonsokolskyi@gmail.com
|
16
|
+
executables:
|
17
|
+
- touchscreen-taps
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- CHANGELOG.md
|
22
|
+
- Gemfile
|
23
|
+
- LICENSE.txt
|
24
|
+
- README.md
|
25
|
+
- Rakefile
|
26
|
+
- bin/console
|
27
|
+
- bin/setup
|
28
|
+
- exe/touchscreen-taps
|
29
|
+
- lib/touchscreen_taps.rb
|
30
|
+
- lib/touchscreen_taps/config.rb
|
31
|
+
- lib/touchscreen_taps/default_config.yml
|
32
|
+
- lib/touchscreen_taps/event.rb
|
33
|
+
- lib/touchscreen_taps/event_filter.rb
|
34
|
+
- lib/touchscreen_taps/event_parser.rb
|
35
|
+
- lib/touchscreen_taps/executor.rb
|
36
|
+
- lib/touchscreen_taps/gesture_buffer.rb
|
37
|
+
- lib/touchscreen_taps/libinput.rb
|
38
|
+
- lib/touchscreen_taps/tap_and_hold_detector.rb
|
39
|
+
- lib/touchscreen_taps/touchscreen_device.rb
|
40
|
+
- lib/touchscreen_taps/version.rb
|
41
|
+
- touchscreen-taps.gemspec
|
42
|
+
homepage: https://github.com/antonsokolskyy/touchscreen-taps
|
43
|
+
licenses:
|
44
|
+
- MIT
|
45
|
+
metadata:
|
46
|
+
homepage_uri: https://github.com/antonsokolskyy/touchscreen-taps
|
47
|
+
source_code_uri: https://github.com/antonsokolskyy/touchscreen-taps
|
48
|
+
changelog_uri: https://github.com/antonsokolskyy/touchscreen-taps/blob/master/CHANGELOG.md
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: 2.3.0
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
requirements: []
|
64
|
+
rubygems_version: 3.0.3
|
65
|
+
signing_key:
|
66
|
+
specification_version: 4
|
67
|
+
summary: Touchscreen taps recognizer
|
68
|
+
test_files: []
|