fusuma 3.0.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4670e37d93cd689661c036a4d2a25361af7a283f407b3ffc98dd1d275d6ef675
4
- data.tar.gz: 78735688ac87ab4c09ebd0f7b69000a56e5543916bd41b490df02b7130525832
3
+ metadata.gz: 30a12dfc770118352a414806a6c37e376eebdf49db24aa347eb904146b855ecf
4
+ data.tar.gz: ef9fb2e5bbbdc4a53eafae83334455890ad99b3c91c43ad0e4ed678f38bb1673
5
5
  SHA512:
6
- metadata.gz: 998e0a7cd21c42870a7b747a0280f4aa55695bea79139f0bef3b2dbcedefc448548f4ed261b2993a67c6e9e5921fa2dcab93b595153fc9b9a04818816fdf605f
7
- data.tar.gz: 8892cf28ab5d7bce157fbf7eca3c9458565585b223d36f9c15f7cc0b2d3d08248c643504f00bc33aac51b88e86270c59b3c886d968e1ce52f7f51a4614dcb16e
6
+ metadata.gz: ecb619087432fc99c51265b91ed1fc21da77e34e13d446a92c29127d15e3e7c35124b2a67df7a184891d76f0ad004151eb1e5d92df170334f5a668eebdb93941
7
+ data.tar.gz: b8da3242044d824d0f39170cf16a3e173214742e01cfe965257a146dfe5a1993d19232d50d5b26dd264956ace6d488ee09b5d7e873de7f45e442ad75646bc41c
data/README.md CHANGED
@@ -403,8 +403,8 @@ Fusuma plugins are provided with the `fusuma-plugin-XXXXX` naming convention and
403
403
  | [fusuma-plugin-sendkey](https://github.com/iberianpig/fusuma-plugin-sendkey) | ![Gem](https://img.shields.io/gem/v/fusuma-plugin-sendkey?color=brightgreen) | Emulates keyboard events(Wayland compatible) |
404
404
  | [fusuma-plugin-wmctrl](https://github.com/iberianpig/fusuma-plugin-wmctrl) | ![Gem](https://img.shields.io/gem/v/fusuma-plugin-wmctrl?color=brightgreen) | Manages Window and Workspace |
405
405
  | [fusuma-plugin-keypress](https://github.com/iberianpig/fusuma-plugin-keypress) | ![Gem](https://img.shields.io/gem/v/fusuma-plugin-keypress?color=brightgreen) | Detecting a combination of key presses and touchpad gestures |
406
- | [fusuma-plugin-tap](https://github.com/iberianpig/fusuma-plugin-tap) | ![Gem](https://img.shields.io/gem/v/fusuma-plugin-tap?color=brightgreen) | Detects Tap gesture |
407
406
  | [fusuma-plugin-appmatcher](https://github.com/iberianpig/fusuma-plugin-appmatcher) | ![Gem](https://img.shields.io/gem/v/fusuma-plugin-appmatcher?color=brightgreen) | Configure app-specific gestures |
407
+ | [fusuma-plugin-thumbsense](https://github.com/iberianpig/fusuma-plugin-thumbsense) | ![Gem](https://img.shields.io/gem/v/fusuma-plugin-thumbsense?color=brightgreen) | Remapper from key to click only while tapping |
408
408
 
409
409
 
410
410
  ### Installation of Fusuma plugins
data/exe/fusuma CHANGED
@@ -27,6 +27,10 @@ opt.on('--log=path/to/file',
27
27
  option[:log_filepath] = v
28
28
  end
29
29
 
30
+ opt.on('--show-config', 'Show config as YAML format which is loaded internally') do |v|
31
+ option[:show_config] = v
32
+ end
33
+
30
34
  opt.on('--device="Device name"',
31
35
  'Open the given device only (DEPRECATED)') do |v|
32
36
  option[:device] = v
data/fusuma.gemspec CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
24
24
  "yard.run" => "yri" # use "yard" to build full HTML docs.
25
25
  }
26
26
 
27
- spec.required_ruby_version = ">= 2.5.1" # https://packages.ubuntu.com/search?keywords=ruby&searchon=names&exact=1&suite=all&section=main
28
- # support bionic (18.04LTS) 2.5.1
27
+ spec.required_ruby_version = ">= 2.7"
28
+ # https://packages.ubuntu.com/search?keywords=ruby&searchon=names&exact=1&suite=all&section=main
29
+ # support focal (20.04LTS) 2.7
29
30
  end
@@ -44,7 +44,7 @@ module Fusuma
44
44
  if @skippable
45
45
  "#{@symbol}(skippable)"
46
46
  else
47
- "#{@symbol}"
47
+ @symbol.to_s
48
48
  end
49
49
  end
50
50
 
@@ -76,6 +76,8 @@ module Fusuma
76
76
  end
77
77
 
78
78
  class << self
79
+ attr_reader :context
80
+
79
81
  # Search with context from load_streamed Config
80
82
  # @param context [Hash]
81
83
  # @return [Object]
@@ -86,20 +88,50 @@ module Fusuma
86
88
  result
87
89
  end
88
90
 
91
+ CONEXT_SEARCH_ORDER = [:no_context, :complete_match_context, :partial_match_context]
89
92
  # Return a matching context from config
90
93
  # @params request_context [Hash]
91
94
  # @return [Hash]
92
- def find_context(request_context, &block)
95
+ def find_context(request_context, fallbacks = CONEXT_SEARCH_ORDER, &block)
93
96
  # Search in blocks in the following order.
94
97
  # 1. primary context(no context)
95
98
  # 2. complete match config[:context] == request_context
96
99
  # 3. partial match config[:context] =~ request_context
100
+ # no_context?(&block) ||
101
+ # complete_match_context(request_context, &block) ||
102
+ # partial_match_context(request_context, &block)
103
+ fallbacks.each do |method|
104
+ result = send(method, request_context, &block)
105
+ return result if result
106
+ end
107
+ end
108
+
109
+ private
110
+
111
+ # No context(primary context)
112
+ # @return [Hash]
113
+ # @return [NilClass]
114
+ def no_context(_request_context, &block)
97
115
  return {} if with_context({}, &block)
116
+ end
98
117
 
118
+ # Complete match request context
119
+ # @param request_context [Hash]
120
+ # @return [Hash] matched context
121
+ # @return [NilClass] if not matched
122
+ def complete_match_context(request_context, &block)
99
123
  Config.instance.keymap.each do |config|
100
124
  next unless config[:context] == request_context
101
125
  return config[:context] if with_context(config[:context], &block)
102
126
  end
127
+ nil
128
+ end
129
+
130
+ # One of multiple request contexts matched
131
+ # @param request_context [Hash]
132
+ # @return [Hash] matched context
133
+ # @return [NilClass] if not matched
134
+ def partial_match_context(request_context, &block)
103
135
  if request_context.keys.size > 1
104
136
  Config.instance.keymap.each do |config|
105
137
  next if config[:context].nil?
@@ -107,11 +139,34 @@ module Fusuma
107
139
  next unless config[:context].all? { |k, v| request_context[k] == v }
108
140
  return config[:context] if with_context(config[:context], &block)
109
141
  end
142
+ nil
110
143
  end
111
144
  end
112
145
 
113
- attr_reader :context
146
+ # Search context for plugin
147
+ # If the plugin_defaults key is a complete match,
148
+ # it is the default value for that plugin, so it is postponed.
149
+ # This is because prioritize overwriting by other plugins.
150
+ # The search order is as follows
151
+ # 1. complete match config[:context].key?(:plugin_defaults)
152
+ # 2. complete match config[:context] == request_context
153
+ # @param request_context [Hash]
154
+ # @return [Hash] matched context
155
+ # @return [NilClass] if not matched
156
+ def plugin_default_context(request_context, &block)
157
+ complete_match_context = nil
158
+ Config.instance.keymap.each do |config|
159
+ next unless config[:context]&.key?(:plugin_defaults)
160
+
161
+ if config[:context][:plugin_defaults] == request_context[:plugin_defaults]
162
+ complete_match_context = config[:context]
163
+ next
164
+ end
114
165
 
166
+ return config[:context] if with_context(config[:context], &block)
167
+ end
168
+ complete_match_context
169
+ end
115
170
  end
116
171
  end
117
172
  end
data/lib/fusuma/config.rb CHANGED
@@ -4,6 +4,7 @@ require_relative "./multi_logger"
4
4
  require_relative "./config/index"
5
5
  require_relative "./config/searcher"
6
6
  require_relative "./config/yaml_duplication_checker"
7
+ require_relative "./plugin/manager"
7
8
  require_relative "./hash_support"
8
9
  require "singleton"
9
10
  require "yaml"
@@ -32,7 +33,7 @@ module Fusuma
32
33
  end
33
34
  end
34
35
 
35
- attr_reader :keymap, :custom_path, :searcher
36
+ attr_reader :custom_path, :searcher
36
37
 
37
38
  def initialize
38
39
  @searcher = Searcher.new
@@ -45,17 +46,47 @@ module Fusuma
45
46
  reload
46
47
  end
47
48
 
49
+ def keymap
50
+ # FIXME: @keymap is not initialized when called from outside Fusuma::Runner like fusuma-senkey
51
+ @keymap || reload.keymap
52
+ end
53
+
48
54
  def reload
55
+ plugin_defaults = plugin_defaults_paths.map do |default_yml|
56
+ {
57
+ context: {plugin_defaults: default_yml.split("/").last.delete_suffix(".yml")},
58
+ **validate(default_yml)[0]
59
+ }
60
+ end
61
+
62
+ config_path = find_config_filepath
63
+ @keymap = validate(config_path) | plugin_defaults
64
+ MultiLogger.info "reload config: #{config_path}"
65
+
66
+ # reset searcher cache
49
67
  @searcher = Searcher.new
50
- path = find_filepath
51
- MultiLogger.info "reload config: #{path}"
52
- @keymap = validate(path)
68
+
53
69
  self
54
70
  rescue InvalidFileError => e
55
71
  MultiLogger.error e.message
56
72
  exit 1
57
73
  end
58
74
 
75
+ # @param key [Symbol]
76
+ # @param base [Config::Index]
77
+ # @return [Hash]
78
+ def fetch_config_params(key, base)
79
+ request_context = {plugin_defaults: base.keys.last.symbol.to_s}
80
+ fallbacks = [:no_context, :plugin_default_context]
81
+ Config::Searcher.find_context(request_context, fallbacks) do
82
+ ret = Config.search(base)
83
+ if ret&.key?(key)
84
+ return ret
85
+ end
86
+ end
87
+ {}
88
+ end
89
+
59
90
  # @return [Hash] If check passes
60
91
  # @raise [InvalidFileError] If check does not pass
61
92
  def validate(path)
@@ -75,7 +106,6 @@ module Fusuma
75
106
  end
76
107
 
77
108
  # @param index [Index]
78
- # @param context [Hash]
79
109
  def search(index)
80
110
  @searcher.search_with_cache(index, location: keymap)
81
111
  end
@@ -95,7 +125,7 @@ module Fusuma
95
125
 
96
126
  private
97
127
 
98
- def find_filepath
128
+ def find_config_filepath
99
129
  filename = "fusuma/config.yml"
100
130
  if custom_path
101
131
  return expand_custom_path if File.exist?(expand_custom_path)
@@ -120,5 +150,12 @@ module Fusuma
120
150
  def expand_default_path(filename)
121
151
  File.expand_path "../../#{filename}", __FILE__
122
152
  end
153
+
154
+ def plugin_defaults_paths
155
+ Plugin::Manager.load_paths.map do |plugin_path|
156
+ yml = plugin_path.gsub(/\.rb$/, ".yml")
157
+ yml if File.exist?(yml)
158
+ end.compact
159
+ end
123
160
  end
124
161
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "fusuma/string_support"
3
+ require_relative "./string_support"
4
4
 
5
5
  module Fusuma
6
6
  # Rename process
@@ -39,6 +39,12 @@ module Fusuma
39
39
  puts device.name
40
40
  end
41
41
  end
42
+
43
+ def print_config
44
+ Config.instance.keymap.each do |conf|
45
+ puts conf.deep_stringify_keys.to_yaml
46
+ end
47
+ end
42
48
  end
43
49
  end
44
50
  end
@@ -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|
@@ -31,14 +31,20 @@ module Fusuma
31
31
  raise NotImplementedError, "override #{self.class.name}##{__method__}"
32
32
  end
33
33
 
34
+ # @param key [Symbol]
35
+ # @param base [Config::Index]
34
36
  # @return [Object]
35
- def config_params(key = nil, base: config_index)
36
- params = Config.search(base) || {}
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)
37
44
 
38
45
  return params unless key
39
46
 
40
- @config_params ||= {}
41
- @config_params["#{base.cache_key},#{key}"] ||=
47
+ @config_params["#{config_index.cache_key},#{key}"] =
42
48
  params.fetch(key, nil).tap do |val|
43
49
  next if val.nil?
44
50
 
@@ -48,14 +54,14 @@ module Fusuma
48
54
  next if param_types.any? { |klass| val.is_a?(klass) }
49
55
 
50
56
  MultiLogger.error("Please fix config.yml.")
51
- MultiLogger.error(":#{base.keys.map(&:symbol)
57
+ MultiLogger.error(":#{config_index.keys.map(&:symbol)
52
58
  .join(" => :")} => :#{key} should be #{param_types.join(" OR ")}.")
53
59
  exit 1
54
60
  end
55
61
  end
56
62
 
57
63
  def config_index
58
- Config::Index.new(self.class.name.gsub("Fusuma::", "").underscore.split("/"))
64
+ @config_index ||= Config::Index.new(self.class.name.gsub("Fusuma::", "").underscore.split("/"))
59
65
  end
60
66
  end
61
67
  end
@@ -11,7 +11,6 @@ module Fusuma
11
11
  DEFAULT_SOURCE = "libinput_gesture_parser"
12
12
  DEFAULT_SECONDS_TO_KEEP = 100
13
13
 
14
-
15
14
  def initialize(*args)
16
15
  super(*args)
17
16
  @cache = {}
@@ -84,15 +83,15 @@ module Fusuma
84
83
  # @param attr [Symbol]
85
84
  # @return [Float]
86
85
  def sum_last10_attrs(attr) # sums last 10 values of attr (or all if length < 10)
87
- cache_entry = ( @cache_sum10[attr] ||= CacheEntry.new(0, 0) )
86
+ cache_entry = (@cache_sum10[attr] ||= CacheEntry.new(0, 0))
88
87
  upd_ev = updating_events
89
- if upd_ev.length > cache_entry.checked + 1 then
88
+ if upd_ev.length > cache_entry.checked + 1
90
89
  cache_entry.value = upd_ev.last(10).map do |gesture_event|
91
90
  gesture_event.record.delta[attr].to_f
92
91
  end.reduce(:+)
93
92
  elsif upd_ev.length > cache_entry.checked
94
93
  cache_entry.value = cache_entry.value + upd_ev[-1].record.delta[attr].to_f - \
95
- (upd_ev.length > 10 ? upd_ev[-11].record.delta[attr].to_f : 0)
94
+ ((upd_ev.length > 10) ? upd_ev[-11].record.delta[attr].to_f : 0)
96
95
  else
97
96
  return cache_entry.value
98
97
  end
@@ -101,7 +100,7 @@ module Fusuma
101
100
  end
102
101
 
103
102
  def updating_events
104
- cache_entry = ( @cache[:updating_events] ||= CacheEntry.new(0, []) )
103
+ cache_entry = (@cache[:updating_events] ||= CacheEntry.new(0, []))
105
104
  cache_entry.checked.upto(@events.length - 1).each do |i|
106
105
  (cache_entry.value << @events[i]) if @events[i].record.status == "update"
107
106
  end
@@ -140,7 +139,7 @@ module Fusuma
140
139
  end
141
140
 
142
141
  def select_by_type(type)
143
- cache_entry = ( @cache_select_by[type] ||= CacheEntry.new(0, self.class.new([])) )
142
+ cache_entry = (@cache_select_by[type] ||= CacheEntry.new(0, self.class.new([])))
144
143
  cache_entry.checked.upto(@events.length - 1).each do |i|
145
144
  (cache_entry.value.events << @events[i]) if @events[i].record.gesture == type
146
145
  end
@@ -150,7 +149,7 @@ module Fusuma
150
149
 
151
150
  def select_from_last_begin
152
151
  return self if empty?
153
- cache_entry = ( @cache[:last_begin] ||= CacheEntry.new(0, nil) )
152
+ cache_entry = (@cache[:last_begin] ||= CacheEntry.new(0, nil))
154
153
 
155
154
  cache_entry.value = (@events.length - 1).downto(cache_entry.checked).find do |i|
156
155
  @events[i].record.status == "begin"
@@ -11,10 +11,14 @@ module Fusuma
11
11
  SOURCES = %w[gesture timer].freeze
12
12
  BUFFER_TYPE = "gesture"
13
13
  GESTURE_RECORD_TYPE = "hold"
14
- Timer = Inputs::TimerInput.instance
15
14
 
16
15
  BASE_THERESHOLD = 0.7
17
16
 
17
+ def initialize(*args)
18
+ super(*args)
19
+ @timer = Inputs::TimerInput.instance
20
+ end
21
+
18
22
  # @param buffers [Array<Buffers::Buffer>]
19
23
  # @return [Events::Event] if event is detected
20
24
  # @return [Array<Events::Event>] if hold end event is detected
@@ -50,10 +54,10 @@ module Fusuma
50
54
  repeat_index = create_repeat_index(finger: finger, status: status)
51
55
  oneshot_index = create_oneshot_index(finger: finger)
52
56
 
53
- if status == "begin" then
57
+ if status == "begin"
54
58
  @timeout = nil
55
- if threshold(index: oneshot_index) < Timer.interval then
56
- Timer.wake_early(Time.now + threshold(index: oneshot_index))
59
+ if threshold(index: oneshot_index) < @timer.interval
60
+ @timer.wake_early(Time.now + threshold(index: oneshot_index))
57
61
  end
58
62
  elsif status == "timer"
59
63
  return if @timeout
@@ -115,10 +119,10 @@ module Fusuma
115
119
 
116
120
  def enough?(index:, holding_time:)
117
121
  diff = threshold(index: index) - holding_time
118
- if diff < 0 then
122
+ if diff < 0
119
123
  true
120
- elsif diff < Timer.interval
121
- Timer.wake_early(Time.now + diff)
124
+ elsif diff < @timer.interval
125
+ @timer.wake_early(Time.now + diff)
122
126
  false
123
127
  end
124
128
  end
@@ -167,7 +167,7 @@ module Fusuma
167
167
  end
168
168
 
169
169
  def calc
170
- @x > @y ? @x.abs : @y.abs
170
+ (@x > @y) ? @x.abs : @y.abs
171
171
  end
172
172
  end
173
173
  end
@@ -14,6 +14,7 @@ module Fusuma
14
14
  {
15
15
  device: [String],
16
16
  "enable-dwt": [TrueClass, FalseClass],
17
+ "disable-dwt": [TrueClass, FalseClass],
17
18
  "enable-tap": [TrueClass, FalseClass],
18
19
  "show-keycodes": [TrueClass, FalseClass],
19
20
  verbose: [TrueClass, FalseClass],
@@ -47,14 +48,16 @@ module Fusuma
47
48
  device = ("--device='#{config_params(:device)}'" if config_params(:device))
48
49
  enable_tap = "--enable-tap" if config_params(:"enable-tap")
49
50
  enable_dwt = "--enable-dwt" if config_params(:"enable-dwt")
51
+ disable_dwt = "--disable-dwt" if config_params(:"disable-dwt")
50
52
  show_keycodes = "--show-keycodes" if config_params(:"show-keycodes")
51
53
  verbose = "--verbose" if config_params(:verbose)
52
54
  [
53
55
  device,
54
- enable_dwt,
55
56
  enable_tap,
57
+ enable_dwt,
58
+ disable_dwt,
56
59
  show_keycodes,
57
- verbose
60
+ verbose,
58
61
  ].compact
59
62
  end
60
63
 
@@ -0,0 +1,3 @@
1
+ plugin:
2
+ inputs:
3
+ libinput_command_input:
@@ -115,6 +115,12 @@ module Fusuma
115
115
  @plugins ||= {}
116
116
  end
117
117
 
118
+ # @return [Array<String>]
119
+ # @example
120
+ # Manager.load_paths
121
+ # => ["/path/to/fusuma/lib/fusuma/plugin/inputs/input.rb",
122
+ # "/path/to/fusuma/lib/fusuma/plugin/inputs/libinput_command_input.rb",
123
+ # "/path/to/fusuma/lib/fusuma/plugin/inputs/timer_input.rb"]
118
124
  def load_paths
119
125
  @load_paths ||= []
120
126
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fusuma
4
- VERSION = "3.0.0"
4
+ VERSION = "3.2.0"
5
5
  end
data/lib/fusuma.rb CHANGED
@@ -27,13 +27,18 @@ module Fusuma
27
27
  MultiLogger.filepath = option[:log_filepath]
28
28
  MultiLogger.instance.debug_mode = option[:verbose]
29
29
 
30
- load_custom_config(option[:config_path])
31
-
32
30
  Plugin::Manager.require_base_plugins
33
31
 
32
+ load_custom_config(option[:config_path])
33
+
34
34
  Environment.dump_information
35
35
  Kernel.exit(0) if option[:version]
36
36
 
37
+ if option[:show_config]
38
+ Environment.print_config
39
+ Kernel.exit(0)
40
+ end
41
+
37
42
  if option[:list]
38
43
  Environment.print_device_list
39
44
  Kernel.exit(0)
@@ -147,7 +152,7 @@ module Fusuma
147
152
  matched_context = nil
148
153
  event = main_events.find do |main_event|
149
154
  matched_context = Config::Searcher.find_context(request_context) do
150
- if modified_record = main_event.record.merge(records: modifiers.map(&:record))
155
+ if (modified_record = main_event.record.merge(records: modifiers.map(&:record)))
151
156
  main_event.record = modified_record
152
157
  elsif !modifiers.empty?
153
158
  # try basically the same, but without any modifiers
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: 3.0.0
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - iberianpig
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-08-19 00:00:00.000000000 Z
11
+ date: 2023-09-24 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Fusuma is multitouch gesture recognizer. This gem makes your touchpad
14
14
  on Linux able to recognize swipes or pinchs and assign command to them. Read installation
@@ -59,6 +59,7 @@ files:
59
59
  - lib/fusuma/plugin/filters/libinput_device_filter.rb
60
60
  - lib/fusuma/plugin/inputs/input.rb
61
61
  - lib/fusuma/plugin/inputs/libinput_command_input.rb
62
+ - lib/fusuma/plugin/inputs/libinput_command_input.yml
62
63
  - lib/fusuma/plugin/inputs/timer_input.rb
63
64
  - lib/fusuma/plugin/manager.rb
64
65
  - lib/fusuma/plugin/parsers/libinput_gesture_parser.rb
@@ -79,14 +80,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
79
80
  requirements:
80
81
  - - ">="
81
82
  - !ruby/object:Gem::Version
82
- version: 2.5.1
83
+ version: '2.7'
83
84
  required_rubygems_version: !ruby/object:Gem::Requirement
84
85
  requirements:
85
86
  - - ">="
86
87
  - !ruby/object:Gem::Version
87
88
  version: '0'
88
89
  requirements: []
89
- rubygems_version: 3.3.26
90
+ rubygems_version: 3.4.10
90
91
  signing_key:
91
92
  specification_version: 4
92
93
  summary: Multitouch gestures with libinput driver, Linux