fusuma 0.9.2 → 0.10.1
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/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
- data/.reek.yml +48 -0
- data/README.md +10 -2
- data/fusuma.gemspec +1 -1
- data/lib/fusuma.rb +11 -9
- data/lib/fusuma/command_executor.rb +34 -0
- data/lib/fusuma/config.rb +34 -26
- data/lib/fusuma/event_stack.rb +87 -0
- data/lib/fusuma/{gesture_action.rb → gesture_event.rb} +14 -14
- data/lib/fusuma/libinput_commands.rb +1 -0
- data/lib/fusuma/pinch.rb +14 -11
- data/lib/fusuma/swipe.rb +17 -13
- data/lib/fusuma/version.rb +1 -1
- metadata +8 -6
- data/ISSUE_TEMPLATE.md +0 -37
- data/lib/fusuma/action_stack.rb +0 -97
- data/lib/fusuma/event_trigger.rb +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 22f6d4a9eb59ada95b2021e8b76b589ec6897cad
|
4
|
+
data.tar.gz: 7a2bb9add47630c73242f701f0cf80c19315b9bf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cff32b3422a740ce8c68cc87db2ac73698cabc01218cfb137d694db5a96cd0bae1b59cf0e362c149e0afa5048b10497dae9c9fae1ab7df5003d2f673e1f6fdd4
|
7
|
+
data.tar.gz: b8f42fdb9cb09d972914f43c0eb0dfaaa64f0516591303c3b6ea62c096783e98606888a22e57dbf113b9ab074161e7c5d5b8385473b9fd074624b4989d74e74b
|
@@ -0,0 +1,32 @@
|
|
1
|
+
---
|
2
|
+
name: Bug report
|
3
|
+
about: Create a report to help us improve
|
4
|
+
|
5
|
+
---
|
6
|
+
|
7
|
+
<!--
|
8
|
+
Before create a report, please check below,
|
9
|
+
* Read Documents. https://github.com/iberianpig/fusuma#installation
|
10
|
+
* Checked that `libinput-debug-events` or `libinput debug-events` worked correctly.
|
11
|
+
* Reproduced the problem in latest version. Update fusuma with `gem update fusuma`
|
12
|
+
* Checked that your issue isn't already filed: https://github.com/iberianpig/fusuma/issues
|
13
|
+
-->
|
14
|
+
|
15
|
+
**Describe the bug**
|
16
|
+
A clear and concise description of what the bug is.
|
17
|
+
|
18
|
+
**To Reproduce**
|
19
|
+
Steps to reproduce the behavior:
|
20
|
+
1. [First Step]
|
21
|
+
2. [Second Step]
|
22
|
+
3. [and so on...]
|
23
|
+
|
24
|
+
**Expected behavior**
|
25
|
+
A clear and concise description of what you expected to happen.
|
26
|
+
|
27
|
+
**Versions**
|
28
|
+
You can get this information from copy and paste the output of `fusuma --version` from the command line. Also, please include the OS and what version of the OS you're running.
|
29
|
+
|
30
|
+
|
31
|
+
**Additional context**
|
32
|
+
Any additional context, your `~/.config/fusuma/config.yml` or data that might be necessary to reproduce the issue.
|
@@ -0,0 +1,17 @@
|
|
1
|
+
---
|
2
|
+
name: Feature request
|
3
|
+
about: Suggest an idea for this project
|
4
|
+
|
5
|
+
---
|
6
|
+
|
7
|
+
**Is your feature request related to a problem? Please describe.**
|
8
|
+
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
9
|
+
|
10
|
+
**Describe the solution you'd like**
|
11
|
+
A clear and concise description of what you want to happen.
|
12
|
+
|
13
|
+
**Describe alternatives you've considered**
|
14
|
+
A clear and concise description of any alternative solutions or features you've considered.
|
15
|
+
|
16
|
+
**Additional context**
|
17
|
+
Add any other context about the feature request here.
|
data/.reek.yml
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
---
|
2
|
+
|
3
|
+
### Generic smell configuration
|
4
|
+
|
5
|
+
detectors:
|
6
|
+
# # You can disable smells completely
|
7
|
+
# IrresponsibleModule:
|
8
|
+
# enabled: false
|
9
|
+
UncommunicativeVariableName:
|
10
|
+
enabled: false
|
11
|
+
|
12
|
+
#
|
13
|
+
# # You can use filters to silence Reek warnings.
|
14
|
+
# # Either because you simply disagree with Reek (we are not the police) or
|
15
|
+
# # because you want to fix this at a later point in time.
|
16
|
+
# NestedIterators:
|
17
|
+
# exclude:
|
18
|
+
# - "MyWorker#self.class_method" # should be refactored
|
19
|
+
# - "AnotherWorker#instance_method" # should be refactored as well
|
20
|
+
#
|
21
|
+
# # A lot of smells allow fine tuning their configuration. You can look up all available options
|
22
|
+
# # in the corresponding smell documentation in /docs. In most cases you probably can just go
|
23
|
+
# # with the defaults as documented in defaults.reek.yml.
|
24
|
+
# DataClump:
|
25
|
+
# max_copies: 3
|
26
|
+
# min_clump_size: 3
|
27
|
+
|
28
|
+
|
29
|
+
# ### Directory specific configuration
|
30
|
+
#
|
31
|
+
# # You can configure smells on a per-directory base.
|
32
|
+
# # E.g. the classic Rails case: controllers smell of NestedIterators (see /docs/Nested-Iterators.md) and
|
33
|
+
# # helpers smell of UtilityFunction (see docs/Utility-Function.md)
|
34
|
+
# # Note that we only allow configuration on a directory level, not a file level, so all paths have to point to directories.
|
35
|
+
# directories:
|
36
|
+
# "web_app/app/controllers":
|
37
|
+
# NestedIterators:
|
38
|
+
# enabled: false
|
39
|
+
# "web_app/app/helpers":
|
40
|
+
# UtilityFunction:
|
41
|
+
# enabled: false
|
42
|
+
|
43
|
+
# ### Excluding directories
|
44
|
+
#
|
45
|
+
# # Directories below will not be scanned at all
|
46
|
+
# exclude_paths:
|
47
|
+
# - lib/legacy
|
48
|
+
# - lib/rake/legacy_tasks
|
data/README.md
CHANGED
@@ -69,7 +69,7 @@ $ mkdir -p ~/.config/fusuma # create config directory
|
|
69
69
|
$ nano ~/.config/fusuma/config.yml # edit config file.
|
70
70
|
```
|
71
71
|
|
72
|
-
### Example (Gesture Mapping for
|
72
|
+
### Example (Gesture Mapping for elementary OS)
|
73
73
|
|
74
74
|
```yaml
|
75
75
|
swipe:
|
@@ -80,8 +80,10 @@ swipe:
|
|
80
80
|
command: 'xdotool key alt+Right'
|
81
81
|
up:
|
82
82
|
command: 'xdotool key ctrl+t'
|
83
|
+
threshold: 1.5
|
83
84
|
down:
|
84
85
|
command: 'xdotool key ctrl+w'
|
86
|
+
threshold: 1.5
|
85
87
|
4:
|
86
88
|
left:
|
87
89
|
command: 'xdotool key super+Left'
|
@@ -94,8 +96,10 @@ swipe:
|
|
94
96
|
pinch:
|
95
97
|
in:
|
96
98
|
command: 'xdotool key ctrl+plus'
|
99
|
+
threshold: 0.1
|
97
100
|
out:
|
98
101
|
command: 'xdotool key ctrl+minus'
|
102
|
+
threshold: 0.1
|
99
103
|
|
100
104
|
threshold:
|
101
105
|
swipe: 1
|
@@ -106,7 +110,7 @@ interval:
|
|
106
110
|
pinch: 1
|
107
111
|
```
|
108
112
|
|
109
|
-
if `command: ` properties are blank, the swipe/pinch doesn't
|
113
|
+
if `command: ` properties are blank, the swipe/pinch doesn't execute command.
|
110
114
|
|
111
115
|
`threshold:` is sensitivity to swipe/pinch. Default value is 1.
|
112
116
|
If the swipe's threshold is `0.5`, shorten swipe-length by half.
|
@@ -147,6 +151,10 @@ swipe:
|
|
147
151
|
2. Open `$ gnome-session-properties`
|
148
152
|
3. Add Fusuma and input location where you checked above's path
|
149
153
|
|
154
|
+
## Support
|
155
|
+
|
156
|
+
[](https://www.patreon.com/iberianpig)
|
157
|
+
|
150
158
|
## Contributing
|
151
159
|
|
152
160
|
Bug reports and pull requests are welcome on GitHub at https://github.com/iberianpig/fusuma. 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/fusuma.gemspec
CHANGED
data/lib/fusuma.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require_relative 'fusuma/version'
|
2
|
-
require_relative 'fusuma/
|
3
|
-
require_relative 'fusuma/
|
4
|
-
require_relative 'fusuma/
|
2
|
+
require_relative 'fusuma/event_stack'
|
3
|
+
require_relative 'fusuma/gesture_event'
|
4
|
+
require_relative 'fusuma/command_executor'
|
5
5
|
require_relative 'fusuma/swipe.rb'
|
6
6
|
require_relative 'fusuma/pinch.rb'
|
7
7
|
require_relative 'fusuma/multi_logger'
|
@@ -68,14 +68,16 @@ module Fusuma
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
+
def initialize
|
72
|
+
@event_stack = EventStack.new
|
73
|
+
end
|
74
|
+
|
71
75
|
def run
|
72
76
|
LibinputCommands.new.debug_events do |line|
|
73
|
-
|
74
|
-
next
|
75
|
-
@
|
76
|
-
@
|
77
|
-
event_trigger = @action_stack.generate_event_trigger
|
78
|
-
event_trigger.exec_command unless event_trigger.nil?
|
77
|
+
gesture_event = GestureEvent.initialize_by(line, Device.ids)
|
78
|
+
next unless gesture_event
|
79
|
+
@event_stack << gesture_event
|
80
|
+
@event_stack.generate_command_executor.tap { |c| c.execute if c }
|
79
81
|
end
|
80
82
|
end
|
81
83
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Fusuma
|
2
|
+
# Execute Command
|
3
|
+
class CommandExecutor
|
4
|
+
def initialize(finger, vector)
|
5
|
+
@finger = finger.to_i
|
6
|
+
@direction = vector.direction
|
7
|
+
@event_type = vector.class::TYPE
|
8
|
+
end
|
9
|
+
attr_reader :finger, :direction, :event_type
|
10
|
+
|
11
|
+
def execute
|
12
|
+
`#{command_or_shortcut}`
|
13
|
+
MultiLogger.info("Execute: #{command_or_shortcut}")
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def command_or_shortcut
|
19
|
+
@command_or_shortcut ||= command || shortcut || no_command
|
20
|
+
end
|
21
|
+
|
22
|
+
def command
|
23
|
+
Config.command(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
def shortcut
|
27
|
+
Config.shortcut(self).tap { |s| return "xdotool key #{s}" if s }
|
28
|
+
end
|
29
|
+
|
30
|
+
def no_command
|
31
|
+
'echo "Command is not assigned"'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/fusuma/config.rb
CHANGED
@@ -6,20 +6,20 @@ module Fusuma
|
|
6
6
|
include Singleton
|
7
7
|
|
8
8
|
class << self
|
9
|
-
def command(
|
10
|
-
instance.command(
|
9
|
+
def command(command_executor)
|
10
|
+
instance.command(command_executor)
|
11
11
|
end
|
12
12
|
|
13
|
-
def shortcut(
|
14
|
-
instance.shortcut(
|
13
|
+
def shortcut(command_executor)
|
14
|
+
instance.shortcut(command_executor)
|
15
15
|
end
|
16
16
|
|
17
|
-
def threshold(
|
18
|
-
instance.threshold(
|
17
|
+
def threshold(command_executor)
|
18
|
+
instance.threshold(command_executor)
|
19
19
|
end
|
20
20
|
|
21
|
-
def interval(
|
22
|
-
instance.interval(
|
21
|
+
def interval(command_executor)
|
22
|
+
instance.interval(command_executor)
|
23
23
|
end
|
24
24
|
|
25
25
|
def reload
|
@@ -31,7 +31,7 @@ module Fusuma
|
|
31
31
|
attr_accessor :custom_path
|
32
32
|
|
33
33
|
def initialize
|
34
|
-
|
34
|
+
self.custom_path = nil
|
35
35
|
reload
|
36
36
|
end
|
37
37
|
|
@@ -41,28 +41,36 @@ module Fusuma
|
|
41
41
|
self
|
42
42
|
end
|
43
43
|
|
44
|
-
def command(
|
45
|
-
seek_index = [*
|
46
|
-
|
44
|
+
def command(command_executor)
|
45
|
+
seek_index = [*event_index(command_executor), 'command']
|
46
|
+
search_config_cached(seek_index)
|
47
47
|
end
|
48
48
|
|
49
|
-
def shortcut(
|
50
|
-
seek_index = [*
|
51
|
-
|
49
|
+
def shortcut(command_executor)
|
50
|
+
seek_index = [*event_index(command_executor), 'shortcut']
|
51
|
+
search_config_cached(seek_index)
|
52
52
|
end
|
53
53
|
|
54
|
-
def threshold(
|
55
|
-
|
56
|
-
|
54
|
+
def threshold(command_executor)
|
55
|
+
seek_index_specific = [*event_index(command_executor), 'threshold']
|
56
|
+
seek_index_global = ['threshold', command_executor.event_type]
|
57
|
+
search_config_cached(seek_index_specific) ||
|
58
|
+
search_config_cached(seek_index_global) || 1
|
57
59
|
end
|
58
60
|
|
59
|
-
def interval(
|
60
|
-
|
61
|
-
|
61
|
+
def interval(command_executor)
|
62
|
+
seek_index_specific = [*event_index(command_executor), 'interval']
|
63
|
+
seek_index_global = ['interval', command_executor.event_type]
|
64
|
+
search_config_cached(seek_index_specific) ||
|
65
|
+
search_config_cached(seek_index_global) || 1
|
62
66
|
end
|
63
67
|
|
64
68
|
private
|
65
69
|
|
70
|
+
def search_config_cached(seek_index)
|
71
|
+
cache(seek_index) { search_config(keymap, seek_index) }
|
72
|
+
end
|
73
|
+
|
66
74
|
def search_config(keymap_node, seek_index)
|
67
75
|
if seek_index == []
|
68
76
|
return nil if keymap_node.is_a? Hash
|
@@ -98,11 +106,11 @@ module Fusuma
|
|
98
106
|
File.expand_path "../../#{filename}", __FILE__
|
99
107
|
end
|
100
108
|
|
101
|
-
def
|
102
|
-
|
103
|
-
finger =
|
104
|
-
direction =
|
105
|
-
[
|
109
|
+
def event_index(command_executor)
|
110
|
+
event_type = command_executor.event_type
|
111
|
+
finger = command_executor.finger
|
112
|
+
direction = command_executor.direction
|
113
|
+
[event_type, finger, direction]
|
106
114
|
end
|
107
115
|
|
108
116
|
def cache(key)
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Fusuma
|
2
|
+
# manage events and generate command
|
3
|
+
class EventStack < Array
|
4
|
+
ELAPSED_TIME = 0.01
|
5
|
+
|
6
|
+
def initialize(*args)
|
7
|
+
super(*args)
|
8
|
+
end
|
9
|
+
|
10
|
+
# @return [CommandExecutor, nil]
|
11
|
+
def generate_command_executor
|
12
|
+
return unless enough_events?
|
13
|
+
vector = generate_vector(detect_event_type)
|
14
|
+
trigger = CommandExecutor.new(finger, vector)
|
15
|
+
return unless vector.enough?(trigger)
|
16
|
+
clear
|
17
|
+
trigger
|
18
|
+
end
|
19
|
+
|
20
|
+
# @params [GestureEvent]
|
21
|
+
def push(gesture_event)
|
22
|
+
super(gesture_event)
|
23
|
+
clear if event_end?
|
24
|
+
end
|
25
|
+
alias << push
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def generate_vector(event_type)
|
30
|
+
case event_type
|
31
|
+
when 'swipe'
|
32
|
+
avg_swipe
|
33
|
+
when 'pinch'
|
34
|
+
avg_pinch
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def finger
|
39
|
+
last.finger
|
40
|
+
end
|
41
|
+
|
42
|
+
def avg_swipe
|
43
|
+
move_x = avg_attrs(:move_x)
|
44
|
+
move_y = avg_attrs(:move_y)
|
45
|
+
Swipe.new(move_x, move_y)
|
46
|
+
end
|
47
|
+
|
48
|
+
def avg_pinch
|
49
|
+
diameter = avg_attrs(:zoom)
|
50
|
+
delta_diameter = diameter - first.zoom
|
51
|
+
Pinch.new(delta_diameter)
|
52
|
+
end
|
53
|
+
|
54
|
+
def sum_attrs(attr)
|
55
|
+
send('map') do |gesture_event|
|
56
|
+
gesture_event.send(attr.to_sym.to_s)
|
57
|
+
end.compact.inject(:+)
|
58
|
+
end
|
59
|
+
|
60
|
+
def avg_attrs(attr)
|
61
|
+
sum_attrs(attr) / length
|
62
|
+
end
|
63
|
+
|
64
|
+
def event_end?
|
65
|
+
last_event_name =~ /_END$/
|
66
|
+
end
|
67
|
+
|
68
|
+
def last_event_name
|
69
|
+
return false if last.class != GestureEvent
|
70
|
+
last.event
|
71
|
+
end
|
72
|
+
|
73
|
+
def enough_events?
|
74
|
+
length > 2
|
75
|
+
end
|
76
|
+
|
77
|
+
def enough_elapsed_time?
|
78
|
+
return false if length.zero?
|
79
|
+
(last.time - first.time) > ELAPSED_TIME
|
80
|
+
end
|
81
|
+
|
82
|
+
def detect_event_type
|
83
|
+
first.event =~ /GESTURE_(.*?)_/
|
84
|
+
Regexp.last_match(1).downcase
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -1,15 +1,15 @@
|
|
1
1
|
module Fusuma
|
2
|
-
# pinch or swipe
|
3
|
-
class
|
4
|
-
def initialize(time,
|
5
|
-
@time
|
6
|
-
@
|
2
|
+
# pinch or swipe or rotate event
|
3
|
+
class GestureEvent
|
4
|
+
def initialize(time, event, finger, directions)
|
5
|
+
@time = time.to_f
|
6
|
+
@event = event
|
7
7
|
@finger = finger
|
8
8
|
@move_x = directions[:move][:x].to_f
|
9
9
|
@move_y = directions[:move][:y].to_f
|
10
10
|
@zoom = directions[:zoom].to_f
|
11
11
|
end
|
12
|
-
attr_reader :time, :
|
12
|
+
attr_reader :time, :event, :finger,
|
13
13
|
:move_x, :move_y, :zoom
|
14
14
|
|
15
15
|
class << self
|
@@ -19,25 +19,25 @@ module Fusuma
|
|
19
19
|
end
|
20
20
|
return if line.to_s =~ /_BEGIN/
|
21
21
|
return unless line.to_s =~ /GESTURE_SWIPE|GESTURE_PINCH/
|
22
|
-
time,
|
23
|
-
MultiLogger.debug(time: time,
|
22
|
+
time, event, finger, directions = gesture_event_arguments(line)
|
23
|
+
MultiLogger.debug(time: time, event: event,
|
24
24
|
finger: finger, directions: directions)
|
25
|
-
|
25
|
+
GestureEvent.new(time, event, finger, directions)
|
26
26
|
end
|
27
27
|
|
28
28
|
private
|
29
29
|
|
30
|
-
def
|
31
|
-
|
30
|
+
def gesture_event_arguments(libinput_line)
|
31
|
+
event, time, finger, other = parse_libinput(libinput_line)
|
32
32
|
move_x, move_y, zoom = parse_finger_directions(other)
|
33
33
|
directions = { move: { x: move_x, y: move_y }, zoom: zoom }
|
34
|
-
[time,
|
34
|
+
[time, event, finger, directions]
|
35
35
|
end
|
36
36
|
|
37
37
|
def parse_libinput(line)
|
38
|
-
_device,
|
38
|
+
_device, event, time, other = line.strip.split(nil, 4)
|
39
39
|
finger, other = other.split(nil, 2)
|
40
|
-
[
|
40
|
+
[event, time, finger, other]
|
41
41
|
end
|
42
42
|
|
43
43
|
def parse_finger_directions(line)
|
data/lib/fusuma/pinch.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
module Fusuma
|
2
2
|
# vector data
|
3
3
|
class Pinch
|
4
|
+
TYPE = 'pinch'.freeze
|
5
|
+
|
4
6
|
BASE_THERESHOLD = 0.3
|
5
7
|
BASE_INTERVAL = 0.05
|
6
8
|
|
@@ -15,33 +17,34 @@ module Fusuma
|
|
15
17
|
'out'
|
16
18
|
end
|
17
19
|
|
18
|
-
def enough?
|
20
|
+
def enough?(trigger)
|
19
21
|
MultiLogger.debug(diameter: diameter)
|
20
|
-
enough_diameter? && enough_interval? &&
|
22
|
+
enough_diameter?(trigger) && enough_interval?(trigger) &&
|
23
|
+
self.class.touch_last_time
|
21
24
|
end
|
22
25
|
|
23
26
|
private
|
24
27
|
|
25
|
-
def enough_diameter?
|
26
|
-
diameter.abs > threshold
|
28
|
+
def enough_diameter?(trigger)
|
29
|
+
diameter.abs > threshold(trigger)
|
27
30
|
end
|
28
31
|
|
29
|
-
def enough_interval?
|
32
|
+
def enough_interval?(trigger)
|
30
33
|
return true if first_time?
|
31
|
-
return true if (Time.now - self.class.last_time) > interval_time
|
34
|
+
return true if (Time.now - self.class.last_time) > interval_time(trigger)
|
32
35
|
false
|
33
36
|
end
|
34
37
|
|
35
38
|
def first_time?
|
36
|
-
self.class.last_time
|
39
|
+
!self.class.last_time
|
37
40
|
end
|
38
41
|
|
39
|
-
def threshold
|
40
|
-
@threshold ||= BASE_THERESHOLD * Config.threshold(
|
42
|
+
def threshold(trigger)
|
43
|
+
@threshold ||= BASE_THERESHOLD * Config.threshold(trigger)
|
41
44
|
end
|
42
45
|
|
43
|
-
def interval_time
|
44
|
-
@interval_time ||= BASE_INTERVAL * Config.interval(
|
46
|
+
def interval_time(trigger)
|
47
|
+
@interval_time ||= BASE_INTERVAL * Config.interval(trigger)
|
45
48
|
end
|
46
49
|
|
47
50
|
class << self
|
data/lib/fusuma/swipe.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
module Fusuma
|
2
2
|
# vector data
|
3
3
|
class Swipe
|
4
|
+
TYPE = 'swipe'.freeze
|
5
|
+
|
4
6
|
BASE_THERESHOLD = 20
|
5
7
|
BASE_INTERVAL = 0.5
|
6
8
|
|
7
|
-
def initialize(
|
8
|
-
@x =
|
9
|
-
@y =
|
9
|
+
def initialize(move_x, move_y)
|
10
|
+
@x = move_x
|
11
|
+
@y = move_y
|
10
12
|
end
|
11
13
|
attr_reader :x, :y
|
12
14
|
|
@@ -15,33 +17,35 @@ module Fusuma
|
|
15
17
|
y > 0 ? 'down' : 'up'
|
16
18
|
end
|
17
19
|
|
18
|
-
def enough?
|
20
|
+
def enough?(trigger)
|
19
21
|
MultiLogger.debug(x: x, y: y)
|
20
|
-
enough_distance? && enough_interval? &&
|
22
|
+
enough_distance?(trigger) && enough_interval?(trigger) &&
|
23
|
+
self.class.touch_last_time
|
21
24
|
end
|
22
25
|
|
23
26
|
private
|
24
27
|
|
25
|
-
def enough_distance?
|
28
|
+
def enough_distance?(trigger)
|
29
|
+
threshold = threshold(trigger)
|
26
30
|
(x.abs > threshold) || (y.abs > threshold)
|
27
31
|
end
|
28
32
|
|
29
|
-
def enough_interval?
|
33
|
+
def enough_interval?(trigger)
|
30
34
|
return true if first_time?
|
31
|
-
return true if (Time.now - self.class.last_time) > interval_time
|
35
|
+
return true if (Time.now - self.class.last_time) > interval_time(trigger)
|
32
36
|
false
|
33
37
|
end
|
34
38
|
|
35
39
|
def first_time?
|
36
|
-
self.class.last_time
|
40
|
+
!self.class.last_time
|
37
41
|
end
|
38
42
|
|
39
|
-
def threshold
|
40
|
-
@threshold ||= BASE_THERESHOLD * Config.threshold(
|
43
|
+
def threshold(trigger)
|
44
|
+
@threshold ||= BASE_THERESHOLD * Config.threshold(trigger)
|
41
45
|
end
|
42
46
|
|
43
|
-
def interval_time
|
44
|
-
@interval_time ||= BASE_INTERVAL * Config.interval(
|
47
|
+
def interval_time(trigger)
|
48
|
+
@interval_time ||= BASE_INTERVAL * Config.interval(trigger)
|
45
49
|
end
|
46
50
|
|
47
51
|
class << self
|
data/lib/fusuma/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fusuma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- iberianpig
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-08-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -118,14 +118,16 @@ executables:
|
|
118
118
|
extensions: []
|
119
119
|
extra_rdoc_files: []
|
120
120
|
files:
|
121
|
+
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
122
|
+
- ".github/ISSUE_TEMPLATE/feature_request.md"
|
121
123
|
- ".github/stale.yml"
|
122
124
|
- ".gitignore"
|
125
|
+
- ".reek.yml"
|
123
126
|
- ".rspec"
|
124
127
|
- ".rubocop.yml"
|
125
128
|
- ".travis.yml"
|
126
129
|
- CODE_OF_CONDUCT.md
|
127
130
|
- Gemfile
|
128
|
-
- ISSUE_TEMPLATE.md
|
129
131
|
- LICENSE
|
130
132
|
- README.md
|
131
133
|
- Rakefile
|
@@ -134,12 +136,12 @@ files:
|
|
134
136
|
- exe/fusuma
|
135
137
|
- fusuma.gemspec
|
136
138
|
- lib/fusuma.rb
|
137
|
-
- lib/fusuma/
|
139
|
+
- lib/fusuma/command_executor.rb
|
138
140
|
- lib/fusuma/config.rb
|
139
141
|
- lib/fusuma/config.yml
|
140
142
|
- lib/fusuma/device.rb
|
141
|
-
- lib/fusuma/
|
142
|
-
- lib/fusuma/
|
143
|
+
- lib/fusuma/event_stack.rb
|
144
|
+
- lib/fusuma/gesture_event.rb
|
143
145
|
- lib/fusuma/libinput_commands.rb
|
144
146
|
- lib/fusuma/multi_logger.rb
|
145
147
|
- lib/fusuma/pinch.rb
|
data/ISSUE_TEMPLATE.md
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
<!--
|
2
|
-
|
3
|
-
Have you read Fusuma's CODE_OF_CONDUCT.md? By filing an Issue, you are expected to comply with it, including treating everyone with respect: https://github.com/iberianpig/fusuma/blob/master/CODE_OF_CONDUCT.md
|
4
|
-
|
5
|
-
-->
|
6
|
-
|
7
|
-
### Prerequisites
|
8
|
-
|
9
|
-
* [ ] Put an X between the brackets on this line if you have done all of the following:
|
10
|
-
* Read Documents. https://github.com/iberianpig/fusuma#installation
|
11
|
-
* Checked that `libinput-debug-events` worked correctly.
|
12
|
-
* Reproduced the problem in latest version. Update fusuma with `gem update fusuma`
|
13
|
-
* Checked that your issue isn't already filed: https://github.com/iberianpig/fusuma/issues
|
14
|
-
|
15
|
-
### Description
|
16
|
-
|
17
|
-
[Description of the issue]
|
18
|
-
|
19
|
-
### Steps to Reproduce
|
20
|
-
|
21
|
-
1. [First Step]
|
22
|
-
2. [Second Step]
|
23
|
-
3. [and so on...]
|
24
|
-
|
25
|
-
**Expected behavior:** [What you expect to happen]
|
26
|
-
|
27
|
-
**Actual behavior:** [What actually happens]
|
28
|
-
|
29
|
-
**Reproduces how often:** [What percentage of the time does it reproduce?]
|
30
|
-
|
31
|
-
### Versions
|
32
|
-
|
33
|
-
You can get this information from copy and pasting the output of `fusuma --version` from the command line. Also, please include the OS and what version of the OS you're running.
|
34
|
-
|
35
|
-
### Additional Information
|
36
|
-
|
37
|
-
Any additional information, your `~/.config/fusuma/config.yml` or data that might be necessary to reproduce the issue.
|
data/lib/fusuma/action_stack.rb
DELETED
@@ -1,97 +0,0 @@
|
|
1
|
-
module Fusuma
|
2
|
-
# manage actions
|
3
|
-
class ActionStack < Array
|
4
|
-
ELAPSED_TIME = 0.01
|
5
|
-
|
6
|
-
def initialize(*args)
|
7
|
-
super(*args)
|
8
|
-
end
|
9
|
-
|
10
|
-
def generate_event_trigger
|
11
|
-
return unless enough_actions?
|
12
|
-
action_type = detect_action_type
|
13
|
-
direction = detect_direction(action_type)
|
14
|
-
return if direction.nil?
|
15
|
-
@last_triggered_time = last.time
|
16
|
-
finger = detect_finger
|
17
|
-
clear
|
18
|
-
EventTrigger.new(finger, direction, action_type)
|
19
|
-
end
|
20
|
-
|
21
|
-
def push(gesture_action)
|
22
|
-
super(gesture_action)
|
23
|
-
clear if action_end?
|
24
|
-
end
|
25
|
-
alias << push
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def detect_direction(action_type)
|
30
|
-
vector = generate_vector(action_type)
|
31
|
-
return if vector && !vector.enough?
|
32
|
-
vector.direction
|
33
|
-
end
|
34
|
-
|
35
|
-
def generate_vector(action_type)
|
36
|
-
case action_type
|
37
|
-
when 'swipe'
|
38
|
-
avg_swipe
|
39
|
-
when 'pinch'
|
40
|
-
avg_pinch
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def detect_finger
|
45
|
-
last.finger
|
46
|
-
end
|
47
|
-
|
48
|
-
def avg_swipe
|
49
|
-
move_x = avg_attrs(:move_x)
|
50
|
-
move_y = avg_attrs(:move_y)
|
51
|
-
Swipe.new(move_x, move_y)
|
52
|
-
end
|
53
|
-
|
54
|
-
def avg_pinch
|
55
|
-
diameter = avg_attrs(:zoom)
|
56
|
-
delta_diameter = diameter - first.zoom
|
57
|
-
Pinch.new(delta_diameter)
|
58
|
-
end
|
59
|
-
|
60
|
-
def sum_attrs(attr)
|
61
|
-
send('map') do |gesture_action|
|
62
|
-
gesture_action.send(attr.to_sym.to_s)
|
63
|
-
end.compact.inject(:+)
|
64
|
-
end
|
65
|
-
|
66
|
-
def avg_attrs(attr)
|
67
|
-
sum_attrs(attr) / length
|
68
|
-
end
|
69
|
-
|
70
|
-
def action_end?
|
71
|
-
last_action_name =~ /_END$/
|
72
|
-
end
|
73
|
-
|
74
|
-
def last_action_name
|
75
|
-
return false if last.class != GestureAction
|
76
|
-
last.action
|
77
|
-
end
|
78
|
-
|
79
|
-
def enough_actions?
|
80
|
-
length > 2
|
81
|
-
end
|
82
|
-
|
83
|
-
def enough_elapsed_time?
|
84
|
-
return false if length.zero?
|
85
|
-
(last.time - first.time) > ELAPSED_TIME
|
86
|
-
end
|
87
|
-
|
88
|
-
def last_triggered_time
|
89
|
-
@last_triggered_time ||= 0
|
90
|
-
end
|
91
|
-
|
92
|
-
def detect_action_type
|
93
|
-
first.action =~ /GESTURE_(.*?)_/
|
94
|
-
Regexp.last_match(1).downcase
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
data/lib/fusuma/event_trigger.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
module Fusuma
|
2
|
-
# manage actions
|
3
|
-
class EventTrigger
|
4
|
-
def initialize(finger, direction, action_type)
|
5
|
-
@finger = finger.to_i
|
6
|
-
@direction = direction
|
7
|
-
@action_type = action_type
|
8
|
-
end
|
9
|
-
attr_reader :finger, :direction, :action_type
|
10
|
-
|
11
|
-
def exec_command
|
12
|
-
return if command.nil?
|
13
|
-
`#{command}`
|
14
|
-
MultiLogger.info("trigger event: #{command}")
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def command
|
20
|
-
Config.command(self).tap { |c| return c if c }
|
21
|
-
Config.shortcut(self).tap { |s| return "xdotool key #{s}" if s }
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|