fusuma 1.9.0 → 2.0.0.pre

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.
@@ -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: []