fusuma-plugin-touchscreen 0.0.1.alpha → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +0 -0
- data/README.md +71 -2
- data/fusuma-plugin-touchscreen.gemspec +3 -2
- data/lib/fusuma/plugin/buffers/touch_buffer.rb +17 -81
- data/lib/fusuma/plugin/detectors/touch_detector.rb +31 -14
- data/lib/fusuma/plugin/detectors/touch_detectors/base.rb +7 -0
- data/lib/fusuma/plugin/detectors/touch_detectors/edge_detector.rb +0 -0
- data/lib/fusuma/plugin/detectors/touch_detectors/hold_detector.rb +11 -3
- data/lib/fusuma/plugin/detectors/touch_detectors/pinch_detector.rb +59 -1
- data/lib/fusuma/plugin/detectors/touch_detectors/rotate_detector.rb +65 -1
- data/lib/fusuma/plugin/detectors/touch_detectors/swipe_detector.rb +11 -9
- data/lib/fusuma/plugin/detectors/touch_detectors/tap_detector.rb +2 -2
- data/lib/fusuma/plugin/detectors/touch_detectors/tap_hold_base.rb +21 -0
- data/lib/fusuma/plugin/devices/touchscreen_device.rb +0 -0
- data/lib/fusuma/plugin/events/records/touch_record.rb +14 -1
- data/lib/fusuma/plugin/events/records/touch_records/base.rb +2 -0
- data/lib/fusuma/plugin/events/records/touch_records/features/direction.rb +36 -0
- data/lib/fusuma/plugin/events/records/touch_records/hold_record.rb +0 -0
- data/lib/fusuma/plugin/events/records/touch_records/pinch_record.rb +23 -0
- data/lib/fusuma/plugin/events/records/touch_records/rotate_record.rb +23 -0
- data/lib/fusuma/plugin/events/records/touch_records/swipe_record.rb +2 -12
- data/lib/fusuma/plugin/events/records/touch_records/tap_record.rb +0 -0
- data/lib/fusuma/plugin/parsers/touch_parser.rb +2 -47
- data/lib/fusuma/plugin/touchscreen/math.rb +68 -0
- data/lib/fusuma/plugin/touchscreen/version.rb +1 -1
- data/lib/fusuma/plugin/touchscreen.rb +0 -0
- data/spec/fusuma/plugin/buffers/touch_buffer_spec.rb +216 -0
- data/spec/fusuma/plugin/detectors/hold_detector_spec.rb +71 -0
- data/spec/fusuma/plugin/detectors/pinch_detector_spec.rb +96 -0
- data/spec/fusuma/plugin/detectors/rotate_detector_spec.rb +123 -0
- data/spec/fusuma/plugin/detectors/swipe_detector_spec.rb +141 -0
- data/spec/fusuma/plugin/detectors/tap_detector_spec.rb +84 -0
- data/spec/fusuma/plugin/detectors/touch_detector_spec.rb +266 -0
- data/spec/fusuma/plugin/devices/touchscreen_device_spec.rb +6 -3
- data/spec/fusuma/plugin/parsers/touch_parser_spec.rb +30 -5
- data/spec/samples/1-finger-hold.txt +0 -0
- data/spec/samples/2-fingers-rotate-clockwise.txt +426 -0
- data/spec/samples/2-fingers-rotate-counterclockwise.txt +459 -0
- data/spec/samples/2-fingers-swipe-right.txt +0 -0
- data/spec/samples/3-fingers-pinch-in.txt +140 -0
- data/spec/samples/3-fingers-pinch-out.txt +171 -0
- data/spec/samples/3-fingers-tap.txt +0 -0
- data/spec/{fixtures/libinput-list-devices_ms-surface-3-pro.txt → samples/libinput-list-devices.txt} +0 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/support/helpers/events_and_records.rb +43 -0
- data/spec/support/shared_contexts/with_touch_buffer.rb +10 -0
- data/spec/support/shared_examples/real_sample.rb +29 -0
- metadata +40 -10
- data/lib/fusuma/utils/angle.rb +0 -12
- data/spec/samples/libinput-devices.txt +0 -182
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fusuma/plugin/detectors/touch_detectors/rotate_detector'
|
3
|
+
|
4
|
+
module Fusuma
|
5
|
+
RSpec.describe Plugin::Detectors::TouchDetectors::RotateDetector do
|
6
|
+
include_context 'with touch buffer'
|
7
|
+
subject { described_class.new }
|
8
|
+
|
9
|
+
before do
|
10
|
+
allow(subject).to receive(:angle_threshold).and_return(0.1)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'no events' do
|
14
|
+
expect(subject.detect(touch_buffer)).to be_nil
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'not moved' do
|
18
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 10, y_mm: 10)))
|
19
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 10, y_mm: 10)))
|
20
|
+
|
21
|
+
expect(subject.detect(touch_buffer)).to be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'moved, only one finger' do
|
25
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 10, y_mm: 10)))
|
26
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 20, y_mm: 20)))
|
27
|
+
|
28
|
+
expect(subject.detect(touch_buffer)).to be_nil
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'moved, 2 fingers, but not enough angle change' do
|
32
|
+
# left finger, a little bit to the down
|
33
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 0, y_mm: 10)))
|
34
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 0, y_mm: 10.1)))
|
35
|
+
# right finger, a little bit to the up
|
36
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 2, x_mm: 20, y_mm: 10)))
|
37
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 2, x_mm: 20, y_mm: 9.99)))
|
38
|
+
|
39
|
+
expect(subject.detect(touch_buffer)).to be_nil
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'moved, 2 fingers, enough angle change, but not same direction' do
|
43
|
+
# left finger, to the down
|
44
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 0, y_mm: 10)))
|
45
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 0, y_mm: 15)))
|
46
|
+
# right finger, to the down
|
47
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 2, x_mm: 20, y_mm: 10)))
|
48
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 2, x_mm: 20, y_mm: 15)))
|
49
|
+
|
50
|
+
expect(subject.detect(touch_buffer)).to be_nil
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'moved, 2 fingers, enough angle change, same direction' do
|
54
|
+
# left finger, to the down
|
55
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 0, y_mm: 10)))
|
56
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 0, y_mm: 15)))
|
57
|
+
# right finger, to the up
|
58
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 2, x_mm: 20, y_mm: 10)))
|
59
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 2, x_mm: 20, y_mm: 5)))
|
60
|
+
|
61
|
+
gesture = subject.detect(touch_buffer)
|
62
|
+
expect(gesture).to be_a Plugin::Events::Records::TouchRecords::RotateRecord
|
63
|
+
expect(gesture.finger).to eq 2
|
64
|
+
expect(gesture.direction).to eq 'counterclockwise'
|
65
|
+
end
|
66
|
+
|
67
|
+
it '2 fingers, clockwise' do
|
68
|
+
# left finger, to the up
|
69
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 0, y_mm: 10)))
|
70
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 0, y_mm: 5)))
|
71
|
+
# right finger, to the down
|
72
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 2, x_mm: 20, y_mm: 10)))
|
73
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 2, x_mm: 20, y_mm: 15)))
|
74
|
+
|
75
|
+
gesture = subject.detect(touch_buffer)
|
76
|
+
expect(gesture).to be_a Plugin::Events::Records::TouchRecords::RotateRecord
|
77
|
+
expect(gesture.finger).to eq 2
|
78
|
+
expect(gesture.direction).to eq 'clockwise'
|
79
|
+
end
|
80
|
+
|
81
|
+
it '3 fingers, one moved into wrong direction' do
|
82
|
+
# left finger, to the up
|
83
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 0, y_mm: 10)))
|
84
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 0, y_mm: 5)))
|
85
|
+
# right finger, to the down
|
86
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 2, x_mm: 20, y_mm: 10)))
|
87
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 2, x_mm: 20, y_mm: 15)))
|
88
|
+
# top finger, to the left
|
89
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 3, x_mm: 10, y_mm: 0)))
|
90
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 3, x_mm: 5, y_mm: 0)))
|
91
|
+
|
92
|
+
expect(subject.detect(touch_buffer)).to be_nil
|
93
|
+
end
|
94
|
+
|
95
|
+
it '3 fingers, same direction' do
|
96
|
+
# left finger, to the up
|
97
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 0, y_mm: 10)))
|
98
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 0, y_mm: 5)))
|
99
|
+
# right finger, to the down
|
100
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 2, x_mm: 20, y_mm: 10)))
|
101
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 2, x_mm: 20, y_mm: 15)))
|
102
|
+
# top finger, to the right
|
103
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 3, x_mm: 10, y_mm: 0)))
|
104
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 3, x_mm: 15, y_mm: 0)))
|
105
|
+
|
106
|
+
gesture = subject.detect(touch_buffer)
|
107
|
+
expect(gesture).to be_a Plugin::Events::Records::TouchRecords::RotateRecord
|
108
|
+
expect(gesture.finger).to eq 3
|
109
|
+
expect(gesture.direction).to eq 'clockwise'
|
110
|
+
end
|
111
|
+
|
112
|
+
it_behaves_like 'real sample',
|
113
|
+
detector_class: Plugin::Detectors::TouchDetectors::RotateDetector,
|
114
|
+
sample_path: 'spec/samples/2-fingers-rotate-clockwise.txt',
|
115
|
+
expected_gesture_class: Plugin::Events::Records::TouchRecords::RotateRecord,
|
116
|
+
expected_gesture_attributes: { finger: 2, direction: 'clockwise' }
|
117
|
+
it_behaves_like 'real sample',
|
118
|
+
detector_class: Plugin::Detectors::TouchDetectors::RotateDetector,
|
119
|
+
sample_path: 'spec/samples/2-fingers-rotate-counterclockwise.txt',
|
120
|
+
expected_gesture_class: Plugin::Events::Records::TouchRecords::RotateRecord,
|
121
|
+
expected_gesture_attributes: { finger: 2, direction: 'counterclockwise' }
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fusuma/plugin/events/event'
|
3
|
+
require 'fusuma/plugin/parsers/touch_parser'
|
4
|
+
require 'fusuma/plugin/buffers/touch_buffer'
|
5
|
+
require 'fusuma/plugin/detectors/touch_detectors/swipe_detector'
|
6
|
+
require 'fusuma/plugin/events/records/touch_records/swipe_record'
|
7
|
+
|
8
|
+
module Fusuma
|
9
|
+
RSpec.describe Plugin::Detectors::TouchDetectors::SwipeDetector do
|
10
|
+
subject { described_class.new }
|
11
|
+
let(:touch_buffer) { Plugin::Buffers::TouchBuffer.new }
|
12
|
+
let(:t) { Time.now }
|
13
|
+
|
14
|
+
before do
|
15
|
+
allow(touch_buffer).to receive(:movement_threshold).and_return(0.5)
|
16
|
+
allow(subject).to receive(:movement_angle_threshold).and_return(30)
|
17
|
+
allow(subject).to receive(:direction_angle_width).and_return(45)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'no events' do
|
21
|
+
expect(subject.detect(touch_buffer)).to be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'not moved' do
|
25
|
+
touch_buffer.buffer(generate_touch_event(time: t - 1, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 10, y_mm: 10)))
|
26
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 10, y_mm: 10)))
|
27
|
+
|
28
|
+
expect(subject.detect(touch_buffer)).to be_nil
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'moved, just one finger' do
|
32
|
+
touch_buffer.buffer(generate_touch_event(time: t - 1, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 10, y_mm: 10)))
|
33
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 20, y_mm: 10)))
|
34
|
+
|
35
|
+
gesture = subject.detect(touch_buffer)
|
36
|
+
expect(gesture).to be_a(Plugin::Events::Records::TouchRecords::SwipeRecord)
|
37
|
+
expect(gesture.finger).to eq(1)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'moved, more fingers, angle difference too big' do
|
41
|
+
touch_buffer.buffer(generate_touch_event(time: t - 1, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 10, y_mm: 10)))
|
42
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 20, y_mm: 10)))
|
43
|
+
touch_buffer.buffer(generate_touch_event(time: t - 1, record: generate_touch_record(status: 'begin', finger: 2, x_mm: 10, y_mm: 10)))
|
44
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 2, x_mm: 10, y_mm: 20)))
|
45
|
+
|
46
|
+
expect(subject.detect(touch_buffer)).to be_nil
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'moved, more fingers, angle difference under movement_angle_threshold' do
|
50
|
+
touch_buffer.buffer(generate_touch_event(time: t - 1, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 10, y_mm: 10)))
|
51
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 20, y_mm: 8)))
|
52
|
+
touch_buffer.buffer(generate_touch_event(time: t - 1, record: generate_touch_record(status: 'begin', finger: 2, x_mm: 10, y_mm: 10)))
|
53
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 2, x_mm: 20, y_mm: 12)))
|
54
|
+
|
55
|
+
gesture = subject.detect(touch_buffer)
|
56
|
+
expect(gesture).to be_a(Plugin::Events::Records::TouchRecords::SwipeRecord)
|
57
|
+
expect(gesture.finger).to eq(2)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'swipe left' do
|
61
|
+
touch_buffer.buffer(generate_touch_event(time: t - 1, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 10, y_mm: 10)))
|
62
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 0, y_mm: 10)))
|
63
|
+
|
64
|
+
gesture = subject.detect(touch_buffer)
|
65
|
+
expect(gesture).to be_a(Plugin::Events::Records::TouchRecords::SwipeRecord)
|
66
|
+
expect(gesture.direction).to eq('left')
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'swipe right' do
|
70
|
+
touch_buffer.buffer(generate_touch_event(time: t - 1, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 0, y_mm: 10)))
|
71
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 10, y_mm: 10)))
|
72
|
+
|
73
|
+
gesture = subject.detect(touch_buffer)
|
74
|
+
expect(gesture).to be_a(Plugin::Events::Records::TouchRecords::SwipeRecord)
|
75
|
+
expect(gesture.direction).to eq('right')
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'swipe up' do
|
79
|
+
touch_buffer.buffer(generate_touch_event(time: t - 1, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 10, y_mm: 10)))
|
80
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 10, y_mm: 0)))
|
81
|
+
|
82
|
+
gesture = subject.detect(touch_buffer)
|
83
|
+
expect(gesture).to be_a(Plugin::Events::Records::TouchRecords::SwipeRecord)
|
84
|
+
expect(gesture.direction).to eq('up')
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'swipe down' do
|
88
|
+
touch_buffer.buffer(generate_touch_event(time: t - 1, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 10, y_mm: 0)))
|
89
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 10, y_mm: 10)))
|
90
|
+
|
91
|
+
gesture = subject.detect(touch_buffer)
|
92
|
+
expect(gesture).to be_a(Plugin::Events::Records::TouchRecords::SwipeRecord)
|
93
|
+
expect(gesture.direction).to eq('down')
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'wrong direction, up left' do
|
97
|
+
touch_buffer.buffer(generate_touch_event(time: t - 1, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 20, y_mm: 20)))
|
98
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 10, y_mm: 10)))
|
99
|
+
|
100
|
+
expect(subject.detect(touch_buffer)).to be_nil
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'wrong direction, up right' do
|
104
|
+
touch_buffer.buffer(generate_touch_event(time: t - 1, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 0, y_mm: 20)))
|
105
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 10, y_mm: 10)))
|
106
|
+
|
107
|
+
expect(subject.detect(touch_buffer)).to be_nil
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'wrong direction, down left' do
|
111
|
+
touch_buffer.buffer(generate_touch_event(time: t - 1, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 20, y_mm: 0)))
|
112
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 10, y_mm: 10)))
|
113
|
+
|
114
|
+
expect(subject.detect(touch_buffer)).to be_nil
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'wrong direction, down right' do
|
118
|
+
touch_buffer.buffer(generate_touch_event(time: t - 1, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 0, y_mm: 0)))
|
119
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 10, y_mm: 10)))
|
120
|
+
|
121
|
+
expect(subject.detect(touch_buffer)).to be_nil
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'works on real data' do
|
125
|
+
parser = Plugin::Parsers::TouchParser.new
|
126
|
+
buffer = Plugin::Buffers::TouchBuffer.new
|
127
|
+
lines = File.readlines("spec/samples/2-fingers-swipe-right.txt").map(&:strip).reject(&:empty?)
|
128
|
+
lines.each do |line|
|
129
|
+
record = parser.parse_record(line)
|
130
|
+
next unless record
|
131
|
+
|
132
|
+
event = Plugin::Events::Event.new(tag: 'libinput_touch_parser', record: record)
|
133
|
+
buffer.buffer(event)
|
134
|
+
end
|
135
|
+
gesture = subject.detect(buffer)
|
136
|
+
expect(gesture).to be_a(Plugin::Events::Records::TouchRecords::SwipeRecord)
|
137
|
+
expect(gesture.finger).to eq(2)
|
138
|
+
expect(gesture.direction).to eq('right')
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fusuma/plugin/events/event'
|
3
|
+
require 'fusuma/plugin/parsers/touch_parser'
|
4
|
+
require 'fusuma/plugin/buffers/touch_buffer'
|
5
|
+
require 'fusuma/plugin/detectors/touch_detectors/tap_detector'
|
6
|
+
require 'fusuma/plugin/events/records/touch_records/tap_record'
|
7
|
+
|
8
|
+
module Fusuma
|
9
|
+
RSpec.describe Plugin::Detectors::TouchDetectors::TapDetector do
|
10
|
+
include_context 'with touch buffer'
|
11
|
+
subject { described_class.new }
|
12
|
+
|
13
|
+
before do
|
14
|
+
allow(touch_buffer).to receive(:movement_threshold).and_return(0.5)
|
15
|
+
allow(subject).to receive(:tap_hold_threshold).and_return(0.5)
|
16
|
+
allow(subject).to receive(:jitter_threshold).and_return(5.0)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'no events' do
|
20
|
+
expect(subject.detect(touch_buffer)).to be nil
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'not began in this cycle' do
|
24
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 10, y_mm: 10)))
|
25
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'end', finger: 1)))
|
26
|
+
|
27
|
+
expect(subject.detect(touch_buffer)).to be nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'not ended in this cycle' do
|
31
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 10, y_mm: 10)))
|
32
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 10, y_mm: 10)))
|
33
|
+
|
34
|
+
expect(subject.detect(touch_buffer)).to be nil
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'moved too much' do
|
38
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 10, y_mm: 10)))
|
39
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'update', finger: 1, x_mm: 20, y_mm: 20)))
|
40
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'end', finger: 1)))
|
41
|
+
|
42
|
+
expect(subject.detect(touch_buffer)).to be nil
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'too long' do
|
46
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 10, y_mm: 10)))
|
47
|
+
touch_buffer.buffer(generate_touch_event(time: t + 0.6, record: generate_touch_record(status: 'end', finger: 1)))
|
48
|
+
|
49
|
+
expect(subject.detect(touch_buffer)).to be nil
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'not moved' do
|
53
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 10, y_mm: 10)))
|
54
|
+
touch_buffer.buffer(generate_touch_event(time: t + 0.1, record: generate_touch_record(status: 'end', finger: 1)))
|
55
|
+
pp touch_buffer.finger_movements
|
56
|
+
|
57
|
+
expect(subject.detect(touch_buffer)).to be_a(Plugin::Events::Records::TouchRecords::TapRecord)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'moved under jitter threshold' do
|
61
|
+
touch_buffer.buffer(generate_touch_event(time: t, record: generate_touch_record(status: 'begin', finger: 1, x_mm: 10, y_mm: 10)))
|
62
|
+
touch_buffer.buffer(generate_touch_event(time: t + 0.1, record: generate_touch_record(status: 'update', finger: 1, x_mm: 10.1, y_mm: 10.1)))
|
63
|
+
touch_buffer.buffer(generate_touch_event(time: t + 0.2, record: generate_touch_record(status: 'end', finger: 1)))
|
64
|
+
|
65
|
+
expect(subject.detect(touch_buffer)).to be_a(Plugin::Events::Records::TouchRecords::TapRecord)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'works on real data' do
|
69
|
+
parser = Plugin::Parsers::TouchParser.new
|
70
|
+
buffer = Plugin::Buffers::TouchBuffer.new
|
71
|
+
lines = File.readlines("spec/samples/3-fingers-tap.txt").map(&:strip).reject(&:empty?)
|
72
|
+
lines.each do |line|
|
73
|
+
record = parser.parse_record(line)
|
74
|
+
next unless record
|
75
|
+
|
76
|
+
event = Plugin::Events::Event.new(tag: 'libinput_touch_parser', record: record)
|
77
|
+
buffer.buffer(event)
|
78
|
+
end
|
79
|
+
gesture = subject.detect(buffer)
|
80
|
+
expect(gesture).to be_a(Plugin::Events::Records::TouchRecords::TapRecord)
|
81
|
+
expect(gesture.finger).to eq(3)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,266 @@
|
|
1
|
+
require 'timecop'
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'fusuma/plugin/events/event'
|
4
|
+
require 'fusuma/plugin/buffers/touch_buffer'
|
5
|
+
require 'fusuma/plugin/detectors/touch_detector'
|
6
|
+
|
7
|
+
module Fusuma
|
8
|
+
RSpec.describe Plugin::Detectors::TouchDetector do
|
9
|
+
subject { described_class.new }
|
10
|
+
let(:detectors) { subject.instance_variable_get(:@detectors) }
|
11
|
+
let(:tap_detector) { detectors.find { |d| d.is_a?(Plugin::Detectors::TouchDetectors::TapDetector) } }
|
12
|
+
let(:hold_detector) { subject.instance_variable_get(:@hold_detector) }
|
13
|
+
let(:swipe_detector) { detectors.find { |d| d.is_a?(Plugin::Detectors::TouchDetectors::SwipeDetector) } }
|
14
|
+
before do
|
15
|
+
expect(:detectors).not_to be_empty
|
16
|
+
expect(tap_detector).to be_a(Plugin::Detectors::TouchDetectors::TapDetector)
|
17
|
+
expect(hold_detector).to be_a(Plugin::Detectors::TouchDetectors::HoldDetector)
|
18
|
+
expect(swipe_detector).to be_a(Plugin::Detectors::TouchDetectors::SwipeDetector)
|
19
|
+
|
20
|
+
detectors.each do |detector|
|
21
|
+
allow(detector).to receive(:detect).and_return(nil)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'does nothing if no matching buffer' do
|
26
|
+
buffer = double('buffer', type: 'not-touch')
|
27
|
+
expect(subject.detect([buffer])).to eq []
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'ends gesture if too much time passed' do
|
31
|
+
allow(hold_detector).to receive(:detect).and_call_original
|
32
|
+
allow(hold_detector).to receive(:tap_hold_threshold).and_return(1)
|
33
|
+
allow(subject).to receive(:event_expire_time).and_return(1)
|
34
|
+
|
35
|
+
t = Time.now
|
36
|
+
touch_buffer = Plugin::Buffers::TouchBuffer.new
|
37
|
+
Timecop.freeze(t - 4) do
|
38
|
+
touch_buffer.buffer(generate_touch_event(record: generate_touch_record(status: 'update'), time: t - 4))
|
39
|
+
end
|
40
|
+
# 2 seconds - enough to detect hold gesture
|
41
|
+
# event is not expired because of there's no event yet
|
42
|
+
events = Timecop.freeze(t - 2) do
|
43
|
+
# here we detect hold gesture, which makes it the last gesture known to the detector
|
44
|
+
subject.detect([touch_buffer])
|
45
|
+
end
|
46
|
+
expect(events.size).to eq 2
|
47
|
+
expect(events[0].record.index.keys.map(&:symbol)).to eq [:hold, 1]
|
48
|
+
expect(events[1].record.index.keys.map(&:symbol)).to eq [:hold, 1, :begin]
|
49
|
+
|
50
|
+
# now the last gesture becomes 1 second old
|
51
|
+
events = Timecop.freeze(t) do
|
52
|
+
timer_buffer = Plugin::Buffers::TimerBuffer.new
|
53
|
+
timer_buffer.buffer(generate_timer_event(time: t))
|
54
|
+
# here we waited for too long time without new events
|
55
|
+
subject.detect([timer_buffer])
|
56
|
+
end
|
57
|
+
|
58
|
+
expect(events.size).to eq 1
|
59
|
+
expect(events.first.record.index.keys.map(&:symbol)).to eq [:hold, 1, :end]
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'ends gesture if end event is found' do
|
63
|
+
allow(hold_detector).to receive(:detect).and_call_original
|
64
|
+
allow(hold_detector).to receive(:tap_hold_threshold).and_return(1)
|
65
|
+
# let's guarantee the event won't be expired
|
66
|
+
allow(subject).to receive(:event_expire_time).and_return(10)
|
67
|
+
|
68
|
+
t = Time.now
|
69
|
+
touch_buffer = Plugin::Buffers::TouchBuffer.new
|
70
|
+
Timecop.freeze(t - 4) do
|
71
|
+
touch_buffer.buffer(generate_touch_event(record: generate_touch_record(status: 'update'), time: t - 4))
|
72
|
+
end
|
73
|
+
# 2 seconds - enough to detect hold gesture
|
74
|
+
# event is not expired because of there's no event yet
|
75
|
+
events = Timecop.freeze(t - 2) do
|
76
|
+
# here we detect hold gesture, which makes it the last gesture known to the detector
|
77
|
+
subject.detect([touch_buffer])
|
78
|
+
end
|
79
|
+
|
80
|
+
# now we send end event
|
81
|
+
events = Timecop.freeze(t) do
|
82
|
+
touch_buffer.buffer(generate_touch_event(record: generate_touch_record(status: 'end'), time: t))
|
83
|
+
subject.detect([touch_buffer])
|
84
|
+
end
|
85
|
+
expect(events.size).to eq 1
|
86
|
+
expect(events[0].record.index.keys.map(&:symbol)).to eq [:hold, 1, :end]
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'ends gesture if new gesture began' do
|
90
|
+
record = Plugin::Events::Records::TouchRecords::HoldRecord.new(finger: 0)
|
91
|
+
allow(hold_detector).to receive(:detect).and_return(record)
|
92
|
+
|
93
|
+
touch_buffer = Plugin::Buffers::TouchBuffer.new
|
94
|
+
touch_buffer.buffer(generate_touch_event)
|
95
|
+
# let's push the hold gesture as the last known gesture
|
96
|
+
events = subject.detect([touch_buffer])
|
97
|
+
expect(events.size).to eq 2
|
98
|
+
expect(events[0].record.index.keys.map(&:symbol)).to eq [:hold, 0]
|
99
|
+
expect(events[1].record.index.keys.map(&:symbol)).to eq [:hold, 0, :begin]
|
100
|
+
|
101
|
+
record = Plugin::Events::Records::TouchRecords::SwipeRecord.new(finger: 0, direction: 'up')
|
102
|
+
allow(hold_detector).to receive(:detect).and_return(nil)
|
103
|
+
allow(swipe_detector).to receive(:detect).and_return(record)
|
104
|
+
|
105
|
+
# now let's not issue any more events for the hold gesture, but start a new swipe gesture
|
106
|
+
touch_buffer.buffer(generate_touch_event)
|
107
|
+
events = subject.detect([touch_buffer])
|
108
|
+
expect(events.size).to eq 3
|
109
|
+
expect(events[0].record.index.keys.map(&:symbol)).to eq [:hold, 0, :end]
|
110
|
+
expect(events[1].record.index.keys.map(&:symbol)).to eq [:swipe, 0, :up]
|
111
|
+
expect(events[2].record.index.keys.map(&:symbol)).to eq [:swipe, 0, :up, :begin]
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'timer tick does nothing if no touch events' do
|
115
|
+
timer_buffer = Plugin::Buffers::TimerBuffer.new
|
116
|
+
timer_buffer.buffer(generate_timer_event)
|
117
|
+
detectors.each do |detector|
|
118
|
+
expect(detector).not_to receive(:detect)
|
119
|
+
end
|
120
|
+
subject.detect([timer_buffer])
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'calls detectors if touch events' do
|
124
|
+
touch_buffer = Plugin::Buffers::TouchBuffer.new
|
125
|
+
touch_buffer.buffer(generate_touch_event)
|
126
|
+
detectors.each do |detector|
|
127
|
+
expect(detector).to receive(:detect)
|
128
|
+
end
|
129
|
+
subject.detect([touch_buffer])
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'calls detectors if timer tick' do
|
133
|
+
touch_buffer = Plugin::Buffers::TouchBuffer.new
|
134
|
+
touch_buffer.buffer(generate_touch_event)
|
135
|
+
# we call detect which won't detect any gesture yet, but will save the reference to the touch buffer
|
136
|
+
subject.detect([touch_buffer])
|
137
|
+
timer_buffer = Plugin::Buffers::TimerBuffer.new
|
138
|
+
timer_buffer.buffer(generate_timer_event)
|
139
|
+
# in fact only the hold detector benefits from timer ticks for now
|
140
|
+
expect(hold_detector).to receive(:detect)
|
141
|
+
subject.detect([timer_buffer])
|
142
|
+
end
|
143
|
+
|
144
|
+
context 'gesture detected' do
|
145
|
+
it 'clears touch buffer' do
|
146
|
+
record = Plugin::Events::Records::TouchRecords::TapRecord.new(finger: 0)
|
147
|
+
allow(tap_detector).to receive(:detect).and_return(record)
|
148
|
+
touch_buffer = Plugin::Buffers::TouchBuffer.new
|
149
|
+
touch_buffer.buffer(generate_touch_event)
|
150
|
+
expect(touch_buffer).to receive(:clear)
|
151
|
+
subject.detect([touch_buffer])
|
152
|
+
end
|
153
|
+
|
154
|
+
context 'repeatable' do
|
155
|
+
it 'creates event' do
|
156
|
+
record = Plugin::Events::Records::TouchRecords::HoldRecord.new(finger: 0)
|
157
|
+
allow(hold_detector).to receive(:detect).and_return(record)
|
158
|
+
touch_buffer = Plugin::Buffers::TouchBuffer.new
|
159
|
+
touch_buffer.buffer(generate_touch_event)
|
160
|
+
events = subject.detect([touch_buffer])
|
161
|
+
expect(events.size).to eq 2
|
162
|
+
expect(events[0].record.index.keys.map(&:symbol)).to eq [:hold, 0]
|
163
|
+
expect(events[1].record.index.keys.map(&:symbol)).to eq [:hold, 0, :begin]
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'matches last known gesture' do
|
167
|
+
record = Plugin::Events::Records::TouchRecords::HoldRecord.new(finger: 0)
|
168
|
+
allow(hold_detector).to receive(:detect).and_return(record)
|
169
|
+
|
170
|
+
touch_buffer = Plugin::Buffers::TouchBuffer.new
|
171
|
+
touch_buffer.buffer(generate_touch_event)
|
172
|
+
# make it the last known gesture
|
173
|
+
subject.detect([touch_buffer])
|
174
|
+
|
175
|
+
touch_buffer.buffer(generate_touch_event)
|
176
|
+
events = subject.detect([touch_buffer])
|
177
|
+
|
178
|
+
expect(events.size).to eq 1
|
179
|
+
expect(events[0].record.index.keys.map(&:symbol)).to eq [:hold, 0, :update]
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'does not match last known gesture' do
|
183
|
+
record = Plugin::Events::Records::TouchRecords::HoldRecord.new(finger: 0)
|
184
|
+
allow(hold_detector).to receive(:detect).and_return(record)
|
185
|
+
|
186
|
+
touch_buffer = Plugin::Buffers::TouchBuffer.new
|
187
|
+
touch_buffer.buffer(generate_touch_event)
|
188
|
+
# make it the last known gesture
|
189
|
+
subject.detect([touch_buffer])
|
190
|
+
|
191
|
+
record = Plugin::Events::Records::TouchRecords::HoldRecord.new(finger: 1)
|
192
|
+
allow(hold_detector).to receive(:detect).and_return(record)
|
193
|
+
touch_buffer.buffer(generate_touch_event)
|
194
|
+
events = subject.detect([touch_buffer])
|
195
|
+
|
196
|
+
expect(events.size).to eq 3
|
197
|
+
expect(events[0].record.index.keys.map(&:symbol)).to eq [:hold, 0, :end]
|
198
|
+
expect(events[1].record.index.keys.map(&:symbol)).to eq [:hold, 1]
|
199
|
+
expect(events[2].record.index.keys.map(&:symbol)).to eq [:hold, 1, :begin]
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'no last known gesture' do
|
203
|
+
record = Plugin::Events::Records::TouchRecords::HoldRecord.new(finger: 0)
|
204
|
+
allow(hold_detector).to receive(:detect).and_return(record)
|
205
|
+
|
206
|
+
touch_buffer = Plugin::Buffers::TouchBuffer.new
|
207
|
+
touch_buffer.buffer(generate_touch_event)
|
208
|
+
events = subject.detect([touch_buffer])
|
209
|
+
|
210
|
+
expect(events.size).to eq 2
|
211
|
+
expect(events[0].record.index.keys.map(&:symbol)).to eq [:hold, 0]
|
212
|
+
expect(events[1].record.index.keys.map(&:symbol)).to eq [:hold, 0, :begin]
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
context 'non-repeatable' do
|
217
|
+
it 'ends last known repeatable gesture if any' do
|
218
|
+
record = Plugin::Events::Records::TouchRecords::HoldRecord.new(finger: 0)
|
219
|
+
allow(hold_detector).to receive(:detect).and_return(record)
|
220
|
+
|
221
|
+
touch_buffer = Plugin::Buffers::TouchBuffer.new
|
222
|
+
touch_buffer.buffer(generate_touch_event)
|
223
|
+
# make it the last known gesture
|
224
|
+
subject.detect([touch_buffer])
|
225
|
+
|
226
|
+
allow(hold_detector).to receive(:detect).and_return(nil)
|
227
|
+
record = Plugin::Events::Records::TouchRecords::TapRecord.new(finger: 0)
|
228
|
+
allow(tap_detector).to receive(:detect).and_return(record)
|
229
|
+
touch_buffer.buffer(generate_touch_event)
|
230
|
+
events = subject.detect([touch_buffer])
|
231
|
+
|
232
|
+
expect(events.size).to eq 2
|
233
|
+
expect(events[0].record.index.keys.map(&:symbol)).to eq [:hold, 0, :end]
|
234
|
+
expect(events[1].record.index.keys.map(&:symbol)).to eq [:tap, 0]
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'creates event' do
|
238
|
+
record = Plugin::Events::Records::TouchRecords::TapRecord.new(finger: 0)
|
239
|
+
allow(tap_detector).to receive(:detect).and_return(record)
|
240
|
+
touch_buffer = Plugin::Buffers::TouchBuffer.new
|
241
|
+
touch_buffer.buffer(generate_touch_event)
|
242
|
+
events = subject.detect([touch_buffer])
|
243
|
+
expect(events.size).to eq 1
|
244
|
+
expect(events[0].record.index.keys.map(&:symbol)).to eq [:tap, 0]
|
245
|
+
end
|
246
|
+
|
247
|
+
it 'does not repeat' do
|
248
|
+
record = Plugin::Events::Records::TouchRecords::TapRecord.new(finger: 0)
|
249
|
+
allow(tap_detector).to receive(:detect).and_return(record)
|
250
|
+
|
251
|
+
touch_buffer = Plugin::Buffers::TouchBuffer.new
|
252
|
+
touch_buffer.buffer(generate_touch_event)
|
253
|
+
events = subject.detect([touch_buffer])
|
254
|
+
expect(events.size).to eq 1
|
255
|
+
expect(events[0].record.index.keys.map(&:symbol)).to eq [:tap, 0]
|
256
|
+
|
257
|
+
touch_buffer.buffer(generate_touch_event)
|
258
|
+
events = subject.detect([touch_buffer])
|
259
|
+
expect(events.size).to eq 1
|
260
|
+
expect(events[0].record.index.keys.map(&:symbol)).to eq [:tap, 0]
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end # context 'gesture detected'
|
264
|
+
|
265
|
+
end # describe Plugin::Detectors::TouchDetector
|
266
|
+
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "spec_helper"
|
4
|
-
require '
|
4
|
+
require 'fusuma/plugin/inputs/libinput_command_input'
|
5
|
+
require 'fusuma/plugin/devices/touchscreen_device'
|
5
6
|
|
6
7
|
module Fusuma
|
7
8
|
RSpec.describe Plugin::Touchscreen::DevicePatch do
|
@@ -21,13 +22,15 @@ module Fusuma
|
|
21
22
|
# that's the only touchscreen device I have :)
|
22
23
|
context 'Microsoft Surface 3 Pro' do
|
23
24
|
let(:list_devices_output) do
|
24
|
-
File.open("./spec/
|
25
|
+
File.open("./spec/samples/libinput-list-devices.txt")
|
25
26
|
end
|
26
27
|
|
27
|
-
it 'detects
|
28
|
+
it 'detects touchscreen' do
|
28
29
|
expect(Device.available.map(&:name)).to include 'NTRG0001:01 1B96:1B05'
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
33
|
+
# TODO: create a test for a dummy device with touch capability
|
34
|
+
|
32
35
|
end
|
33
36
|
end
|