fusuma 1.9.0 → 2.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './buffer.rb'
4
+
5
+ module Fusuma
6
+ module Plugin
7
+ module Buffers
8
+ # manage events and generate command
9
+ class TimerBuffer < Buffer
10
+ DEFAULT_SOURCE = 'timer_input'
11
+ DEFAULT_SECONDS_TO_KEEP = 60
12
+
13
+ def config_param_types
14
+ {
15
+ 'source': [String],
16
+ 'seconds_to_keep': [Float, Integer]
17
+ }
18
+ end
19
+
20
+ # @param event [Event]
21
+ # @return [Buffer, NilClass]
22
+ def buffer(event)
23
+ return if event&.tag != source
24
+
25
+ @events.push(event)
26
+ self
27
+ end
28
+
29
+ def clear_expired(current_time: Time.now)
30
+ @seconds_to_keep ||= (config_params(:seconds_to_keep) || DEFAULT_SECONDS_TO_KEEP)
31
+ @events.each do |e|
32
+ break if current_time - e.time < @seconds_to_keep
33
+
34
+ MultiLogger.debug("#{self.class.name}##{__method__}")
35
+
36
+ @events.delete(e)
37
+ end
38
+ end
39
+
40
+ def empty?
41
+ @events.empty?
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -14,10 +14,13 @@ module Fusuma
14
14
  Delta = Struct.new(:move_x, :move_y, :zoom, :rotate)
15
15
 
16
16
  # @param status [String]
17
+ # @param gesture [String]
18
+ # @param finger [String, Integer]
19
+ # @param direction [Delta, NilClass]
17
20
  def initialize(status:, gesture:, finger:, direction:)
18
21
  @status = status
19
22
  @gesture = gesture
20
- @finger = finger
23
+ @finger = finger.to_i
21
24
  @direction = direction
22
25
  end
23
26
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'posix/spawn'
3
4
  require_relative './executor.rb'
4
5
 
5
6
  module Fusuma
@@ -12,11 +13,8 @@ module Fusuma
12
13
  break unless command
13
14
 
14
15
  MultiLogger.info(command: command)
15
- pid = fork do
16
- Process.daemon(true)
17
- exec(command.to_s)
18
- end
19
16
 
17
+ pid = POSIX::Spawn.spawn(command.to_s)
20
18
  Process.detach(pid)
21
19
  end
22
20
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './filter.rb'
4
+ require_relative '../../libinput_command.rb'
5
+
6
+ module Fusuma
7
+ module Plugin
8
+ module Filters
9
+ # Filter device log
10
+ class LibinputTimeoutFilter < Filter
11
+ DEFAULT_SOURCE = 'libinput_command_input'
12
+
13
+ # @return [TrueClass] when keeping it
14
+ # @return [FalseClass] when discarding it
15
+ def keep?(record)
16
+ record.to_s == LibinputCommand::TIMEOUT_MESSAGE
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -5,15 +5,37 @@ require_relative '../events/event.rb'
5
5
 
6
6
  module Fusuma
7
7
  module Plugin
8
- # input class
9
8
  module Inputs
10
9
  # Inherite this base
10
+ # @abstract Subclass and override {#io} to implement
11
11
  class Input < Base
12
- def run
12
+ # Wait multiple inputs until it becomes readable
13
+ # and read lines with nonblock
14
+ # @param inputs [Array<Input>]
15
+ # @return Event
16
+ def self.select(inputs)
17
+ ios = IO.select(inputs.map(&:io))
18
+ io = ios&.first&.first
19
+
20
+ input = inputs.find { |i| i.io == io }
21
+
22
+ begin
23
+ line = io.readline_nonblock("\n").chomp
24
+ rescue StandardError => e
25
+ warn e
26
+ exit 1
27
+ end
28
+
29
+ input.create_event(record: line)
30
+ end
31
+
32
+ # @return [IO]
33
+ def io
13
34
  raise NotImplementedError, "override #{self.class.name}##{__method__}"
14
35
  end
15
36
 
16
- def event(record: 'dummy input')
37
+ # @return [Event]
38
+ def create_event(record: 'dummy input')
17
39
  Events::Event.new(tag: tag, record: record).tap do |e|
18
40
  MultiLogger.debug(input_event: e)
19
41
  end
@@ -26,3 +48,24 @@ module Fusuma
26
48
  end
27
49
  end
28
50
  end
51
+
52
+ # ref: https://github.com/Homebrew/brew/blob/6b2dbbc96f7d8aa12f9b8c9c60107c9cc58befc4/Library/Homebrew/extend/io.rb
53
+ class IO
54
+ def readline_nonblock(sep = $INPUT_RECORD_SEPARATOR)
55
+ line = +''
56
+ buffer = +''
57
+
58
+ loop do
59
+ break if buffer == sep
60
+
61
+ read_nonblock(1, buffer)
62
+ line.concat(buffer)
63
+ end
64
+
65
+ line.freeze
66
+ rescue IO::WaitReadable, EOFError => e
67
+ raise e if line.empty?
68
+
69
+ line.freeze
70
+ end
71
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../../libinput_command.rb'
3
4
  require_relative './input.rb'
4
5
 
5
6
  module Fusuma
@@ -13,16 +14,29 @@ module Fusuma
13
14
  'enable-dwt': [TrueClass, FalseClass],
14
15
  'enable-tap': [TrueClass, FalseClass],
15
16
  'show-keycodes': [TrueClass, FalseClass],
16
- 'verbose': [TrueClass, FalseClass]
17
+ 'verbose': [TrueClass, FalseClass],
18
+ 'libinput-debug-events': [String],
19
+ 'libinput-list-devices': [String]
17
20
  }
18
21
  end
19
22
 
20
- def run
21
- LibinputCommand.new(libinput_options: libinput_options).debug_events do |line|
22
- yield event(record: line)
23
- end
23
+ # @return [IO]
24
+ def io
25
+ @io ||= command.debug_events
24
26
  end
25
27
 
28
+ # @return [LibinputCommand]
29
+ def command
30
+ @command ||= LibinputCommand.new(
31
+ libinput_options: libinput_options,
32
+ commands: {
33
+ debug_events_command: debug_events_command,
34
+ list_devices_command: list_devices_command
35
+ }
36
+ )
37
+ end
38
+
39
+ # @return [Array]
26
40
  def libinput_options
27
41
  device = ("--device='#{config_params(:device)}'" if config_params(:device))
28
42
  enable_tap = '--enable-tap' if config_params(:'enable-tap')
@@ -37,6 +51,14 @@ module Fusuma
37
51
  verbose
38
52
  ].compact
39
53
  end
54
+
55
+ def debug_events_command
56
+ config_params(:'libinput-debug-events')
57
+ end
58
+
59
+ def list_devices_command
60
+ config_params(:'libinput-list-devices')
61
+ end
40
62
  end
41
63
  end
42
64
  end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './input.rb'
4
+
5
+ module Fusuma
6
+ module Plugin
7
+ module Inputs
8
+ # libinput commands wrapper
9
+ class TimerInput < Input
10
+ DEFAULT_INTERVAL = 0.3
11
+ def config_param_types
12
+ {
13
+ 'interval': [Float]
14
+ }
15
+ end
16
+
17
+ attr_reader :writer
18
+
19
+ def io
20
+ @io ||= begin
21
+ reader, writer = create_io
22
+ @pid = start(reader, writer)
23
+
24
+ reader
25
+ end
26
+ end
27
+
28
+ def start(reader, writer)
29
+ pid = fork do
30
+ timer_loop(reader, writer)
31
+ end
32
+ Process.detach(pid)
33
+ writer.close
34
+ pid
35
+ end
36
+
37
+ def timer_loop(reader, writer)
38
+ reader.close
39
+ begin
40
+ loop do
41
+ sleep interval
42
+ writer.puts 'timer'
43
+ end
44
+ rescue Errno::EPIPE
45
+ exit 0
46
+ rescue StandardError => e
47
+ MultiLogger.error e
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def create_io
54
+ IO.pipe
55
+ end
56
+
57
+ def interval
58
+ config_params(:interval) || DEFAULT_INTERVAL
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fusuma
4
- VERSION = '1.9.0'
4
+ VERSION = '2.0.0.pre'
5
5
  end
metadata CHANGED
@@ -1,163 +1,23 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fusuma
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.0
4
+ version: 2.0.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - iberianpig
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-03-30 00:00:00.000000000 Z
11
+ date: 2020-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: posix-spawn
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: coveralls
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: github_changelog_generator
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '1.14'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '1.14'
55
- - !ruby/object:Gem::Dependency
56
- name: pry-byebug
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '3.4'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '3.4'
69
- - !ruby/object:Gem::Dependency
70
- name: pry-doc
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: pry-inline
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: rake
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: '13.0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '13.0'
111
- - !ruby/object:Gem::Dependency
112
- name: reek
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- - !ruby/object:Gem::Dependency
126
- name: rspec
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - "~>"
130
- - !ruby/object:Gem::Version
131
- version: '3.0'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - "~>"
137
- - !ruby/object:Gem::Version
138
- version: '3.0'
139
- - !ruby/object:Gem::Dependency
140
- name: rubocop
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - ">="
144
- - !ruby/object:Gem::Version
145
- version: '0'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - ">="
151
- - !ruby/object:Gem::Version
152
- version: '0'
153
- - !ruby/object:Gem::Dependency
154
- name: yard
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - ">="
158
- - !ruby/object:Gem::Version
159
- version: '0'
160
- type: :development
20
+ type: :runtime
161
21
  prerelease: false
162
22
  version_requirements: !ruby/object:Gem::Requirement
163
23
  requirements:
@@ -177,6 +37,7 @@ files:
177
37
  - ".github/FUNDING.yml"
178
38
  - ".github/ISSUE_TEMPLATE/bug_report.md"
179
39
  - ".github/ISSUE_TEMPLATE/feature_request.md"
40
+ - ".github/pull_request_template.md"
180
41
  - ".github/stale.yml"
181
42
  - ".gitignore"
182
43
  - ".reek.yml"
@@ -186,6 +47,7 @@ files:
186
47
  - ".travis.yml"
187
48
  - CHANGELOG.md
188
49
  - CODE_OF_CONDUCT.md
50
+ - CONTRIBUTING.md
189
51
  - Gemfile
190
52
  - LICENSE
191
53
  - README.md
@@ -198,6 +60,8 @@ files:
198
60
  - lib/fusuma/config.rb
199
61
  - lib/fusuma/config.yml
200
62
  - lib/fusuma/config/index.rb
63
+ - lib/fusuma/config/searcher.rb
64
+ - lib/fusuma/config/yaml_duplication_checker.rb
201
65
  - lib/fusuma/device.rb
202
66
  - lib/fusuma/environment.rb
203
67
  - lib/fusuma/libinput_command.rb
@@ -205,6 +69,7 @@ files:
205
69
  - lib/fusuma/plugin/base.rb
206
70
  - lib/fusuma/plugin/buffers/buffer.rb
207
71
  - lib/fusuma/plugin/buffers/gesture_buffer.rb
72
+ - lib/fusuma/plugin/buffers/timer_buffer.rb
208
73
  - lib/fusuma/plugin/detectors/detector.rb
209
74
  - lib/fusuma/plugin/detectors/pinch_detector.rb
210
75
  - lib/fusuma/plugin/detectors/rotate_detector.rb
@@ -218,8 +83,10 @@ files:
218
83
  - lib/fusuma/plugin/executors/executor.rb
219
84
  - lib/fusuma/plugin/filters/filter.rb
220
85
  - lib/fusuma/plugin/filters/libinput_device_filter.rb
86
+ - lib/fusuma/plugin/filters/libinput_timeout_filter.rb
221
87
  - lib/fusuma/plugin/inputs/input.rb
222
88
  - lib/fusuma/plugin/inputs/libinput_command_input.rb
89
+ - lib/fusuma/plugin/inputs/timer_input.rb
223
90
  - lib/fusuma/plugin/manager.rb
224
91
  - lib/fusuma/plugin/parsers/libinput_gesture_parser.rb
225
92
  - lib/fusuma/plugin/parsers/parser.rb
@@ -229,7 +96,7 @@ licenses:
229
96
  - MIT
230
97
  metadata:
231
98
  yard.run: yri
232
- post_install_message:
99
+ post_install_message:
233
100
  rdoc_options: []
234
101
  require_paths:
235
102
  - lib
@@ -240,12 +107,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
240
107
  version: '2.3'
241
108
  required_rubygems_version: !ruby/object:Gem::Requirement
242
109
  requirements:
243
- - - ">="
110
+ - - ">"
244
111
  - !ruby/object:Gem::Version
245
- version: '0'
112
+ version: 1.3.1
246
113
  requirements: []
247
- rubygems_version: 3.0.3
248
- signing_key:
114
+ rubygems_version: 3.1.4
115
+ signing_key:
249
116
  specification_version: 4
250
117
  summary: Multitouch gestures with libinput dirver on X11, Linux
251
118
  test_files: []