fusuma 2.5.1 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +55 -34
- data/exe/fusuma +4 -0
- data/fusuma.gemspec +3 -2
- data/lib/fusuma/config/index.rb +19 -46
- data/lib/fusuma/config/searcher.rb +68 -60
- data/lib/fusuma/config.rb +43 -6
- data/lib/fusuma/custom_process.rb +34 -2
- data/lib/fusuma/device.rb +1 -0
- data/lib/fusuma/environment.rb +6 -0
- data/lib/fusuma/hash_support.rb +22 -0
- data/lib/fusuma/multi_logger.rb +16 -0
- data/lib/fusuma/plugin/base.rb +16 -7
- data/lib/fusuma/plugin/buffers/gesture_buffer.rb +62 -6
- data/lib/fusuma/plugin/detectors/detector.rb +10 -9
- data/lib/fusuma/plugin/detectors/hold_detector.rb +28 -14
- data/lib/fusuma/plugin/detectors/pinch_detector.rb +10 -10
- data/lib/fusuma/plugin/detectors/rotate_detector.rb +4 -11
- data/lib/fusuma/plugin/detectors/swipe_detector.rb +8 -16
- data/lib/fusuma/plugin/events/records/gesture_record.rb +5 -2
- data/lib/fusuma/plugin/events/records/index_record.rb +1 -1
- data/lib/fusuma/plugin/executors/command_executor.rb +2 -2
- data/lib/fusuma/plugin/executors/executor.rb +1 -4
- data/lib/fusuma/plugin/filters/libinput_device_filter.rb +2 -1
- data/lib/fusuma/plugin/inputs/input.rb +14 -36
- data/lib/fusuma/plugin/inputs/libinput_command_input.yml +3 -0
- data/lib/fusuma/plugin/inputs/timer_input.rb +36 -21
- data/lib/fusuma/plugin/manager.rb +17 -6
- data/lib/fusuma/version.rb +1 -1
- data/lib/fusuma.rb +51 -36
- metadata +5 -4
@@ -1,21 +1,53 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require_relative "./string_support"
|
4
4
|
|
5
5
|
module Fusuma
|
6
6
|
# Rename process
|
7
7
|
module CustomProcess
|
8
8
|
attr_writer :proctitle
|
9
9
|
|
10
|
+
def child_pids
|
11
|
+
@child_pids ||= []
|
12
|
+
end
|
13
|
+
|
10
14
|
def fork
|
11
|
-
Process.fork do
|
15
|
+
pid = Process.fork do
|
12
16
|
Process.setproctitle(proctitle)
|
17
|
+
set_trap # for child process
|
13
18
|
yield
|
14
19
|
end
|
20
|
+
child_pids << pid
|
21
|
+
pid
|
22
|
+
end
|
23
|
+
|
24
|
+
def shutdown
|
25
|
+
child_pids.each do |pid|
|
26
|
+
Process.kill("TERM", pid)
|
27
|
+
rescue Errno::ESRCH
|
28
|
+
# ignore
|
29
|
+
end
|
30
|
+
|
31
|
+
child_pids.each do |pid|
|
32
|
+
Process.wait(pid)
|
33
|
+
rescue Errno::ECHILD
|
34
|
+
# ignore
|
35
|
+
end
|
15
36
|
end
|
16
37
|
|
17
38
|
def proctitle
|
18
39
|
@proctitle ||= self.class.name.underscore
|
19
40
|
end
|
41
|
+
|
42
|
+
def set_trap
|
43
|
+
Signal.trap("INT") {
|
44
|
+
shutdown
|
45
|
+
exit
|
46
|
+
} # Trap ^C
|
47
|
+
Signal.trap("TERM") {
|
48
|
+
shutdown
|
49
|
+
exit
|
50
|
+
} # Trap `Kill `
|
51
|
+
end
|
20
52
|
end
|
21
53
|
end
|
data/lib/fusuma/device.rb
CHANGED
@@ -66,6 +66,7 @@ module Fusuma
|
|
66
66
|
line_parser = LineParser.new
|
67
67
|
|
68
68
|
libinput_command = Plugin::Inputs::LibinputCommandInput.new.command
|
69
|
+
# note: this libinput command takes a nontrivial amout of time (~200ms)
|
69
70
|
libinput_command.list_devices do |line|
|
70
71
|
line_parser.push(line)
|
71
72
|
end
|
data/lib/fusuma/environment.rb
CHANGED
data/lib/fusuma/hash_support.rb
CHANGED
@@ -2,6 +2,28 @@
|
|
2
2
|
|
3
3
|
# Patch to hash
|
4
4
|
class Hash
|
5
|
+
# activesupport-5.2.0/lib/active_support/core_ext/hash/deep_merge.rb
|
6
|
+
def deep_merge(other_hash, &block)
|
7
|
+
dup.deep_merge!(other_hash, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Same as +deep_merge+, but modifies +self+.
|
11
|
+
def deep_merge!(other_hash, &block)
|
12
|
+
merge!(other_hash) do |key, this_val, other_val|
|
13
|
+
if this_val.is_a?(Hash) && other_val.is_a?(Hash)
|
14
|
+
this_val.deep_merge(other_val, &block)
|
15
|
+
elsif block
|
16
|
+
block.call(key, this_val, other_val)
|
17
|
+
else
|
18
|
+
other_val
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def deep_stringify_keys
|
24
|
+
deep_transform_keys(&:to_s)
|
25
|
+
end
|
26
|
+
|
5
27
|
# activesupport-4.1.1/lib/active_support/core_ext/hash/keys.rb
|
6
28
|
def deep_symbolize_keys
|
7
29
|
deep_transform_keys do |key|
|
data/lib/fusuma/multi_logger.rb
CHANGED
@@ -32,6 +32,8 @@ module Fusuma
|
|
32
32
|
def debug(msg)
|
33
33
|
return unless debug_mode?
|
34
34
|
|
35
|
+
return if ignore_pattern?(msg)
|
36
|
+
|
35
37
|
super(msg)
|
36
38
|
end
|
37
39
|
|
@@ -47,6 +49,20 @@ module Fusuma
|
|
47
49
|
debug_mode
|
48
50
|
end
|
49
51
|
|
52
|
+
def ignore_pattern?(msg)
|
53
|
+
# TODO: configurable from config.yml
|
54
|
+
pattern = /timer_input/
|
55
|
+
case msg
|
56
|
+
when Hash
|
57
|
+
e = msg.values.find { |v| v.is_a? Fusuma::Plugin::Events::Event }
|
58
|
+
return unless e
|
59
|
+
|
60
|
+
e.tag.match?(pattern)
|
61
|
+
else
|
62
|
+
false
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
50
66
|
class << self
|
51
67
|
def info(msg)
|
52
68
|
instance.info(msg)
|
data/lib/fusuma/plugin/base.rb
CHANGED
@@ -8,7 +8,6 @@ module Fusuma
|
|
8
8
|
module Plugin
|
9
9
|
# Create a Plugin Class with extending this class
|
10
10
|
class Base
|
11
|
-
include CustomProcess
|
12
11
|
# when inherited from subclass
|
13
12
|
def self.inherited(subclass)
|
14
13
|
super
|
@@ -22,20 +21,30 @@ module Fusuma
|
|
22
21
|
Manager.plugins[name]
|
23
22
|
end
|
24
23
|
|
24
|
+
# @abstract override `#shutdown` to implement
|
25
|
+
def shutdown
|
26
|
+
end
|
27
|
+
|
25
28
|
# config parameter name and Type of the value of parameter
|
26
29
|
# @return [Hash]
|
27
30
|
def config_param_types
|
28
31
|
raise NotImplementedError, "override #{self.class.name}##{__method__}"
|
29
32
|
end
|
30
33
|
|
34
|
+
# @param key [Symbol]
|
35
|
+
# @param base [Config::Index]
|
31
36
|
# @return [Object]
|
32
|
-
def config_params(key = nil
|
33
|
-
|
37
|
+
def config_params(key = nil)
|
38
|
+
@config_params ||= {}
|
39
|
+
if @config_params["#{config_index.cache_key},#{key}"]
|
40
|
+
return @config_params["#{config_index.cache_key},#{key}"]
|
41
|
+
end
|
42
|
+
|
43
|
+
params = Config.instance.fetch_config_params(key, config_index)
|
34
44
|
|
35
45
|
return params unless key
|
36
46
|
|
37
|
-
@config_params
|
38
|
-
@config_params["#{base.cache_key},#{key}"] ||=
|
47
|
+
@config_params["#{config_index.cache_key},#{key}"] =
|
39
48
|
params.fetch(key, nil).tap do |val|
|
40
49
|
next if val.nil?
|
41
50
|
|
@@ -45,14 +54,14 @@ module Fusuma
|
|
45
54
|
next if param_types.any? { |klass| val.is_a?(klass) }
|
46
55
|
|
47
56
|
MultiLogger.error("Please fix config.yml.")
|
48
|
-
MultiLogger.error(":#{
|
57
|
+
MultiLogger.error(":#{config_index.keys.map(&:symbol)
|
49
58
|
.join(" => :")} => :#{key} should be #{param_types.join(" OR ")}.")
|
50
59
|
exit 1
|
51
60
|
end
|
52
61
|
end
|
53
62
|
|
54
63
|
def config_index
|
55
|
-
Config::Index.new(self.class.name.gsub("Fusuma::", "").underscore.split("/"))
|
64
|
+
@config_index ||= Config::Index.new(self.class.name.gsub("Fusuma::", "").underscore.split("/"))
|
56
65
|
end
|
57
66
|
end
|
58
67
|
end
|
@@ -7,9 +7,24 @@ module Fusuma
|
|
7
7
|
module Buffers
|
8
8
|
# manage events and generate command
|
9
9
|
class GestureBuffer < Buffer
|
10
|
+
CacheEntry = Struct.new(:checked, :value)
|
10
11
|
DEFAULT_SOURCE = "libinput_gesture_parser"
|
11
12
|
DEFAULT_SECONDS_TO_KEEP = 100
|
12
13
|
|
14
|
+
def initialize(*args)
|
15
|
+
super(*args)
|
16
|
+
@cache = {}
|
17
|
+
@cache_select_by = {}
|
18
|
+
@cache_sum10 = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def clear
|
22
|
+
super.clear
|
23
|
+
@cache = {}
|
24
|
+
@cache_select_by = {}
|
25
|
+
@cache_sum10 = {}
|
26
|
+
end
|
27
|
+
|
13
28
|
def config_param_types
|
14
29
|
{
|
15
30
|
source: [String],
|
@@ -40,6 +55,9 @@ module Fusuma
|
|
40
55
|
MultiLogger.debug("#{self.class.name}##{__method__}")
|
41
56
|
|
42
57
|
@events.delete(e)
|
58
|
+
@cache = {}
|
59
|
+
@cache_select_by = {}
|
60
|
+
@cache_sum10 = {}
|
43
61
|
end
|
44
62
|
end
|
45
63
|
|
@@ -59,11 +77,35 @@ module Fusuma
|
|
59
77
|
def sum_attrs(attr)
|
60
78
|
updating_events.map do |gesture_event|
|
61
79
|
gesture_event.record.delta[attr].to_f
|
62
|
-
end.
|
80
|
+
end.reduce(:+)
|
81
|
+
end
|
82
|
+
|
83
|
+
# @param attr [Symbol]
|
84
|
+
# @return [Float]
|
85
|
+
def sum_last10_attrs(attr) # sums last 10 values of attr (or all if length < 10)
|
86
|
+
cache_entry = (@cache_sum10[attr] ||= CacheEntry.new(0, 0))
|
87
|
+
upd_ev = updating_events
|
88
|
+
if upd_ev.length > cache_entry.checked + 1
|
89
|
+
cache_entry.value = upd_ev.last(10).map do |gesture_event|
|
90
|
+
gesture_event.record.delta[attr].to_f
|
91
|
+
end.reduce(:+)
|
92
|
+
elsif upd_ev.length > cache_entry.checked
|
93
|
+
cache_entry.value = cache_entry.value + upd_ev[-1].record.delta[attr].to_f - \
|
94
|
+
((upd_ev.length > 10) ? upd_ev[-11].record.delta[attr].to_f : 0)
|
95
|
+
else
|
96
|
+
return cache_entry.value
|
97
|
+
end
|
98
|
+
cache_entry.checked = upd_ev.length
|
99
|
+
cache_entry.value
|
63
100
|
end
|
64
101
|
|
65
102
|
def updating_events
|
66
|
-
@
|
103
|
+
cache_entry = (@cache[:updating_events] ||= CacheEntry.new(0, []))
|
104
|
+
cache_entry.checked.upto(@events.length - 1).each do |i|
|
105
|
+
(cache_entry.value << @events[i]) if @events[i].record.status == "update"
|
106
|
+
end
|
107
|
+
cache_entry.checked = @events.length
|
108
|
+
cache_entry.value
|
67
109
|
end
|
68
110
|
|
69
111
|
# @param attr [Symbol]
|
@@ -96,14 +138,28 @@ module Fusuma
|
|
96
138
|
self.class.new events
|
97
139
|
end
|
98
140
|
|
141
|
+
def select_by_type(type)
|
142
|
+
cache_entry = (@cache_select_by[type] ||= CacheEntry.new(0, self.class.new([])))
|
143
|
+
cache_entry.checked.upto(@events.length - 1).each do |i|
|
144
|
+
(cache_entry.value.events << @events[i]) if @events[i].record.gesture == type
|
145
|
+
end
|
146
|
+
cache_entry.checked = @events.length
|
147
|
+
cache_entry.value
|
148
|
+
end
|
149
|
+
|
99
150
|
def select_from_last_begin
|
100
151
|
return self if empty?
|
152
|
+
cache_entry = (@cache[:last_begin] ||= CacheEntry.new(0, nil))
|
153
|
+
|
154
|
+
cache_entry.value = (@events.length - 1).downto(cache_entry.checked).find do |i|
|
155
|
+
@events[i].record.status == "begin"
|
156
|
+
end || cache_entry.value
|
157
|
+
cache_entry.checked = @events.length
|
101
158
|
|
102
|
-
|
103
|
-
return GestureBuffer.new([]) if
|
159
|
+
return self if cache_entry.value == 0
|
160
|
+
return GestureBuffer.new([]) if cache_entry.value.nil?
|
104
161
|
|
105
|
-
|
106
|
-
GestureBuffer.new(@events[index_last_begin..-1])
|
162
|
+
GestureBuffer.new(@events[cache_entry.value..-1])
|
107
163
|
end
|
108
164
|
end
|
109
165
|
end
|
@@ -8,9 +8,18 @@ module Fusuma
|
|
8
8
|
module Detectors
|
9
9
|
# Inherite this base
|
10
10
|
class Detector < Base
|
11
|
+
def initialize(*args)
|
12
|
+
super(*args)
|
13
|
+
@tag = self.class.tag
|
14
|
+
@type = self.class.type
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :tag
|
18
|
+
attr_reader :type
|
19
|
+
|
11
20
|
# @return [Array<String>]
|
12
21
|
def sources
|
13
|
-
@
|
22
|
+
@sources ||= self.class.const_get(:SOURCES)
|
14
23
|
end
|
15
24
|
|
16
25
|
# Always watch buffers and detect them or not
|
@@ -43,14 +52,6 @@ module Fusuma
|
|
43
52
|
@last_time.nil?
|
44
53
|
end
|
45
54
|
|
46
|
-
def tag
|
47
|
-
self.class.tag
|
48
|
-
end
|
49
|
-
|
50
|
-
def type
|
51
|
-
self.class.type
|
52
|
-
end
|
53
|
-
|
54
55
|
class << self
|
55
56
|
def tag
|
56
57
|
name.split("Detectors::").last.underscore
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "./detector"
|
4
|
+
require_relative "../inputs/timer_input"
|
4
5
|
|
5
6
|
module Fusuma
|
6
7
|
module Plugin
|
@@ -13,6 +14,11 @@ module Fusuma
|
|
13
14
|
|
14
15
|
BASE_THERESHOLD = 0.7
|
15
16
|
|
17
|
+
def initialize(*args)
|
18
|
+
super(*args)
|
19
|
+
@timer = Inputs::TimerInput.instance
|
20
|
+
end
|
21
|
+
|
16
22
|
# @param buffers [Array<Buffers::Buffer>]
|
17
23
|
# @return [Events::Event] if event is detected
|
18
24
|
# @return [Array<Events::Event>] if hold end event is detected
|
@@ -21,16 +27,15 @@ module Fusuma
|
|
21
27
|
hold_buffer = find_hold_buffer(buffers)
|
22
28
|
return if hold_buffer.empty?
|
23
29
|
|
24
|
-
|
30
|
+
last_hold = hold_buffer.events.last
|
25
31
|
|
26
32
|
timer_buffer = buffers.find { |b| b.type == "timer" }
|
27
|
-
|
33
|
+
last_timer = timer_buffer.events.last
|
28
34
|
|
29
35
|
finger = hold_buffer.finger
|
30
|
-
holding_time = calc_holding_time(hold_events:
|
36
|
+
holding_time = calc_holding_time(hold_events: hold_buffer.events, last_timer: last_timer)
|
31
37
|
|
32
|
-
|
33
|
-
status = case hold_events.last.record.status
|
38
|
+
status = case last_hold.record.status
|
34
39
|
when "begin"
|
35
40
|
if holding_time.zero?
|
36
41
|
"begin"
|
@@ -42,16 +47,19 @@ module Fusuma
|
|
42
47
|
when "end"
|
43
48
|
"end"
|
44
49
|
else
|
45
|
-
last_record =
|
50
|
+
last_record = last_hold.record.status
|
46
51
|
raise "Unexpected Status:#{last_record.status} in #{last_record}"
|
47
52
|
end
|
48
53
|
|
49
54
|
repeat_index = create_repeat_index(finger: finger, status: status)
|
50
55
|
oneshot_index = create_oneshot_index(finger: finger)
|
51
56
|
|
52
|
-
|
53
|
-
|
54
|
-
|
57
|
+
if status == "begin"
|
58
|
+
@timeout = nil
|
59
|
+
if threshold(index: oneshot_index) < @timer.interval
|
60
|
+
@timer.wake_early(Time.now + threshold(index: oneshot_index))
|
61
|
+
end
|
62
|
+
elsif status == "timer"
|
55
63
|
return if @timeout
|
56
64
|
|
57
65
|
return unless enough?(index: oneshot_index, holding_time: holding_time)
|
@@ -97,12 +105,12 @@ module Fusuma
|
|
97
105
|
def find_hold_buffer(buffers)
|
98
106
|
buffers.find { |b| b.type == BUFFER_TYPE }
|
99
107
|
.select_from_last_begin
|
100
|
-
.
|
108
|
+
.select_by_type(GESTURE_RECORD_TYPE)
|
101
109
|
end
|
102
110
|
|
103
|
-
def calc_holding_time(hold_events:,
|
104
|
-
last_time = if
|
105
|
-
|
111
|
+
def calc_holding_time(hold_events:, last_timer:)
|
112
|
+
last_time = if last_timer && (hold_events.last.time < last_timer.time)
|
113
|
+
last_timer.time
|
106
114
|
else
|
107
115
|
hold_events.last.time
|
108
116
|
end
|
@@ -110,7 +118,13 @@ module Fusuma
|
|
110
118
|
end
|
111
119
|
|
112
120
|
def enough?(index:, holding_time:)
|
113
|
-
|
121
|
+
diff = threshold(index: index) - holding_time
|
122
|
+
if diff < 0
|
123
|
+
true
|
124
|
+
elsif diff < @timer.interval
|
125
|
+
@timer.wake_early(Time.now + diff)
|
126
|
+
false
|
127
|
+
end
|
114
128
|
end
|
115
129
|
|
116
130
|
def threshold(index:)
|
@@ -19,7 +19,7 @@ module Fusuma
|
|
19
19
|
def detect(buffers)
|
20
20
|
gesture_buffer = buffers.find { |b| b.type == BUFFER_TYPE }
|
21
21
|
.select_from_last_begin
|
22
|
-
.
|
22
|
+
.select_by_type(GESTURE_RECORD_TYPE)
|
23
23
|
|
24
24
|
updating_events = gesture_buffer.updating_events
|
25
25
|
return if updating_events.empty?
|
@@ -100,10 +100,10 @@ module Fusuma
|
|
100
100
|
def create_repeat_index(gesture:, finger:, direction:, status:)
|
101
101
|
Config::Index.new(
|
102
102
|
[
|
103
|
-
Config::Index::Key.new(gesture),
|
104
|
-
Config::Index::Key.new(finger.to_i),
|
105
|
-
Config::Index::Key.new(direction, skippable: true),
|
106
|
-
Config::Index::Key.new(status)
|
103
|
+
Config::Index::Key.new(gesture), # 'pinch'
|
104
|
+
Config::Index::Key.new(finger.to_i), # 2, 3, 4
|
105
|
+
Config::Index::Key.new(direction, skippable: true), # 'in', 'out'
|
106
|
+
Config::Index::Key.new(status) # 'begin', 'update', 'end'
|
107
107
|
]
|
108
108
|
)
|
109
109
|
end
|
@@ -115,9 +115,9 @@ module Fusuma
|
|
115
115
|
def create_oneshot_index(gesture:, finger:, direction:)
|
116
116
|
Config::Index.new(
|
117
117
|
[
|
118
|
-
Config::Index::Key.new(gesture),
|
119
|
-
Config::Index::Key.new(finger.to_i, skippable: true),
|
120
|
-
Config::Index::Key.new(direction)
|
118
|
+
Config::Index::Key.new(gesture), # 'pinch'
|
119
|
+
Config::Index::Key.new(finger.to_i, skippable: true), # 2, 3, 4
|
120
|
+
Config::Index::Key.new(direction) # 'in', 'out'
|
121
121
|
]
|
122
122
|
)
|
123
123
|
end
|
@@ -161,9 +161,9 @@ module Fusuma
|
|
161
161
|
|
162
162
|
def calc
|
163
163
|
if @target > @base
|
164
|
-
IN
|
165
|
-
else
|
166
164
|
OUT
|
165
|
+
else
|
166
|
+
IN
|
167
167
|
end
|
168
168
|
end
|
169
169
|
end
|
@@ -19,21 +19,14 @@ module Fusuma
|
|
19
19
|
def detect(buffers)
|
20
20
|
gesture_buffer = buffers.find { |b| b.type == BUFFER_TYPE }
|
21
21
|
.select_from_last_begin
|
22
|
-
.
|
22
|
+
.select_by_type(GESTURE_RECORD_TYPE)
|
23
23
|
|
24
24
|
updating_events = gesture_buffer.updating_events
|
25
25
|
return if updating_events.empty?
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
last_10.sum_attrs(:rotate) / updating_time
|
31
|
-
else
|
32
|
-
updating_time = 100 * (updating_events.last.time - updating_events.first.time)
|
33
|
-
gesture_buffer.sum_attrs(:rotate) / updating_time
|
34
|
-
end
|
35
|
-
|
36
|
-
return if updating_events.empty?
|
27
|
+
updating_time = 100 * (updating_events[-1].time -
|
28
|
+
(updating_events[-10] || updating_events.first).time)
|
29
|
+
oneshot_angle = gesture_buffer.sum_last10_attrs(:rotate) / updating_time
|
37
30
|
|
38
31
|
finger = gesture_buffer.finger
|
39
32
|
|
@@ -19,22 +19,15 @@ module Fusuma
|
|
19
19
|
def detect(buffers)
|
20
20
|
gesture_buffer = buffers.find { |b| b.type == BUFFER_TYPE }
|
21
21
|
.select_from_last_begin
|
22
|
-
.
|
22
|
+
.select_by_type(GESTURE_RECORD_TYPE)
|
23
23
|
|
24
24
|
updating_events = gesture_buffer.updating_events
|
25
25
|
return if updating_events.empty?
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
last_10.sum_attrs(:move_y) / updating_time]
|
32
|
-
else
|
33
|
-
updating_time = 100 * (updating_events.last.time - updating_events.first.time)
|
34
|
-
[gesture_buffer.sum_attrs(:move_x) / updating_time,
|
35
|
-
gesture_buffer.sum_attrs(:move_y) / updating_time]
|
36
|
-
end
|
37
|
-
(gesture_buffer.sum_attrs(:move_x) / updating_time)
|
27
|
+
updating_time = 100 * (updating_events.last.time -
|
28
|
+
(updating_events[-10] || updating_events.first).time)
|
29
|
+
oneshot_move_x = gesture_buffer.sum_last10_attrs(:move_x) / updating_time
|
30
|
+
oneshot_move_y = gesture_buffer.sum_last10_attrs(:move_y) / updating_time
|
38
31
|
|
39
32
|
finger = gesture_buffer.finger
|
40
33
|
status = case gesture_buffer.events.last.record.status
|
@@ -67,8 +60,7 @@ module Fusuma
|
|
67
60
|
|
68
61
|
oneshot_direction = Direction.new(move_x: oneshot_move_x, move_y: oneshot_move_y).to_s
|
69
62
|
oneshot_quantity = Quantity.new(move_x: oneshot_move_x, move_y: oneshot_move_y).to_f
|
70
|
-
oneshot_index = create_oneshot_index(gesture: type, finger: finger,
|
71
|
-
direction: oneshot_direction)
|
63
|
+
oneshot_index = create_oneshot_index(gesture: type, finger: finger, direction: oneshot_direction)
|
72
64
|
if enough_oneshot_threshold?(index: oneshot_index, quantity: oneshot_quantity)
|
73
65
|
return [
|
74
66
|
create_event(record: Events::Records::IndexRecord.new(
|
@@ -109,7 +101,7 @@ module Fusuma
|
|
109
101
|
Config::Index.new(
|
110
102
|
[
|
111
103
|
Config::Index::Key.new(gesture),
|
112
|
-
Config::Index::Key.new(finger.to_i
|
104
|
+
Config::Index::Key.new(finger.to_i),
|
113
105
|
Config::Index::Key.new(direction)
|
114
106
|
]
|
115
107
|
)
|
@@ -175,7 +167,7 @@ module Fusuma
|
|
175
167
|
end
|
176
168
|
|
177
169
|
def calc
|
178
|
-
@x > @y ? @x.abs : @y.abs
|
170
|
+
(@x > @y) ? @x.abs : @y.abs
|
179
171
|
end
|
180
172
|
end
|
181
173
|
end
|
@@ -11,9 +11,12 @@ module Fusuma
|
|
11
11
|
# define gesture format
|
12
12
|
attr_reader :status, :gesture, :finger, :delta
|
13
13
|
|
14
|
-
Delta = Struct.new(
|
14
|
+
Delta = Struct.new(
|
15
|
+
:move_x, :move_y,
|
15
16
|
:unaccelerated_x, :unaccelerated_y,
|
16
|
-
:zoom,
|
17
|
+
:zoom,
|
18
|
+
:rotate
|
19
|
+
)
|
17
20
|
|
18
21
|
# @param status [String]
|
19
22
|
# @param gesture [String]
|
@@ -39,14 +39,14 @@ module Fusuma
|
|
39
39
|
# @return [String]
|
40
40
|
def search_command(event)
|
41
41
|
command_index = Config::Index.new([*event.record.index.keys, :command])
|
42
|
-
Config.search(command_index)
|
42
|
+
Config.instance.search(command_index)
|
43
43
|
end
|
44
44
|
|
45
45
|
# @param event [Event]
|
46
46
|
# @return [Float]
|
47
47
|
def args_accel(event)
|
48
48
|
accel_index = Config::Index.new([*event.record.index.keys, :accel])
|
49
|
-
(Config.search(accel_index) || 1).to_f
|
49
|
+
(Config.instance.search(accel_index) || 1).to_f
|
50
50
|
end
|
51
51
|
end
|
52
52
|
end
|
@@ -26,12 +26,9 @@ module Fusuma
|
|
26
26
|
end
|
27
27
|
|
28
28
|
# @param event [Events::Event]
|
29
|
-
# @param time [Time]
|
30
29
|
# @return [TrueClass, FalseClass]
|
31
30
|
def enough_interval?(event)
|
32
|
-
|
33
|
-
# Otherwise, a wrong index will cause invalid intervals.
|
34
|
-
return true if event.record.index.with_context.keys.any? { |key| key.symbol == :end }
|
31
|
+
return true if event.record.index.keys.any? { |key| key.symbol == :end }
|
35
32
|
|
36
33
|
return false if @wait_until && event.time < @wait_until
|
37
34
|
|
@@ -25,7 +25,8 @@ module Fusuma
|
|
25
25
|
keep_device.reset
|
26
26
|
return false
|
27
27
|
end
|
28
|
-
|
28
|
+
device_id = record.to_s.match(/\S*/, 1).to_s
|
29
|
+
keep_device.all.map(&:id).include?(device_id)
|
29
30
|
end
|
30
31
|
|
31
32
|
def keep_device
|