fusuma 0.9.2 → 0.10.1

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
  SHA1:
3
- metadata.gz: 45e3e3c6fb9720c3ba2b9a5326654a14b2a2daa7
4
- data.tar.gz: 86240a1c766363f3d028b46740aea8fbaaf8de8f
3
+ metadata.gz: 22f6d4a9eb59ada95b2021e8b76b589ec6897cad
4
+ data.tar.gz: 7a2bb9add47630c73242f701f0cf80c19315b9bf
5
5
  SHA512:
6
- metadata.gz: c9d835c20d8ad97b03c9cac293961a10ee61fa8458d5b3e1ce79352896127cf81eb5cc3b3e3c5573b34774a17545106ef796c950e98c1418a4d97b85130c4799
7
- data.tar.gz: 11699f299247c0bd80ec568189e040726d1785827aeb9ae756e9147d37eb04c982a689e67ea158fb1277f575a5fc4acdce66313f5a663f4f05ee26dcd01f43e6
6
+ metadata.gz: cff32b3422a740ce8c68cc87db2ac73698cabc01218cfb137d694db5a96cd0bae1b59cf0e362c149e0afa5048b10497dae9c9fae1ab7df5003d2f673e1f6fdd4
7
+ data.tar.gz: b8f42fdb9cb09d972914f43c0eb0dfaaa64f0516591303c3b6ea62c096783e98606888a22e57dbf113b9ab074161e7c5d5b8385473b9fd074624b4989d74e74b
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+
5
+ ---
6
+
7
+ <!--
8
+ Before create a report, please check below,
9
+ * Read Documents. https://github.com/iberianpig/fusuma#installation
10
+ * Checked that `libinput-debug-events` or `libinput debug-events` worked correctly.
11
+ * Reproduced the problem in latest version. Update fusuma with `gem update fusuma`
12
+ * Checked that your issue isn't already filed: https://github.com/iberianpig/fusuma/issues
13
+ -->
14
+
15
+ **Describe the bug**
16
+ A clear and concise description of what the bug is.
17
+
18
+ **To Reproduce**
19
+ Steps to reproduce the behavior:
20
+ 1. [First Step]
21
+ 2. [Second Step]
22
+ 3. [and so on...]
23
+
24
+ **Expected behavior**
25
+ A clear and concise description of what you expected to happen.
26
+
27
+ **Versions**
28
+ You can get this information from copy and paste the output of `fusuma --version` from the command line. Also, please include the OS and what version of the OS you're running.
29
+
30
+
31
+ **Additional context**
32
+ Any additional context, your `~/.config/fusuma/config.yml` or data that might be necessary to reproduce the issue.
@@ -0,0 +1,17 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+
5
+ ---
6
+
7
+ **Is your feature request related to a problem? Please describe.**
8
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9
+
10
+ **Describe the solution you'd like**
11
+ A clear and concise description of what you want to happen.
12
+
13
+ **Describe alternatives you've considered**
14
+ A clear and concise description of any alternative solutions or features you've considered.
15
+
16
+ **Additional context**
17
+ Add any other context about the feature request here.
@@ -0,0 +1,48 @@
1
+ ---
2
+
3
+ ### Generic smell configuration
4
+
5
+ detectors:
6
+ # # You can disable smells completely
7
+ # IrresponsibleModule:
8
+ # enabled: false
9
+ UncommunicativeVariableName:
10
+ enabled: false
11
+
12
+ #
13
+ # # You can use filters to silence Reek warnings.
14
+ # # Either because you simply disagree with Reek (we are not the police) or
15
+ # # because you want to fix this at a later point in time.
16
+ # NestedIterators:
17
+ # exclude:
18
+ # - "MyWorker#self.class_method" # should be refactored
19
+ # - "AnotherWorker#instance_method" # should be refactored as well
20
+ #
21
+ # # A lot of smells allow fine tuning their configuration. You can look up all available options
22
+ # # in the corresponding smell documentation in /docs. In most cases you probably can just go
23
+ # # with the defaults as documented in defaults.reek.yml.
24
+ # DataClump:
25
+ # max_copies: 3
26
+ # min_clump_size: 3
27
+
28
+
29
+ # ### Directory specific configuration
30
+ #
31
+ # # You can configure smells on a per-directory base.
32
+ # # E.g. the classic Rails case: controllers smell of NestedIterators (see /docs/Nested-Iterators.md) and
33
+ # # helpers smell of UtilityFunction (see docs/Utility-Function.md)
34
+ # # Note that we only allow configuration on a directory level, not a file level, so all paths have to point to directories.
35
+ # directories:
36
+ # "web_app/app/controllers":
37
+ # NestedIterators:
38
+ # enabled: false
39
+ # "web_app/app/helpers":
40
+ # UtilityFunction:
41
+ # enabled: false
42
+
43
+ # ### Excluding directories
44
+ #
45
+ # # Directories below will not be scanned at all
46
+ # exclude_paths:
47
+ # - lib/legacy
48
+ # - lib/rake/legacy_tasks
data/README.md CHANGED
@@ -69,7 +69,7 @@ $ mkdir -p ~/.config/fusuma # create config directory
69
69
  $ nano ~/.config/fusuma/config.yml # edit config file.
70
70
  ```
71
71
 
72
- ### Example (Gesture Mapping for Elementary OS)
72
+ ### Example (Gesture Mapping for elementary OS)
73
73
 
74
74
  ```yaml
75
75
  swipe:
@@ -80,8 +80,10 @@ swipe:
80
80
  command: 'xdotool key alt+Right'
81
81
  up:
82
82
  command: 'xdotool key ctrl+t'
83
+ threshold: 1.5
83
84
  down:
84
85
  command: 'xdotool key ctrl+w'
86
+ threshold: 1.5
85
87
  4:
86
88
  left:
87
89
  command: 'xdotool key super+Left'
@@ -94,8 +96,10 @@ swipe:
94
96
  pinch:
95
97
  in:
96
98
  command: 'xdotool key ctrl+plus'
99
+ threshold: 0.1
97
100
  out:
98
101
  command: 'xdotool key ctrl+minus'
102
+ threshold: 0.1
99
103
 
100
104
  threshold:
101
105
  swipe: 1
@@ -106,7 +110,7 @@ interval:
106
110
  pinch: 1
107
111
  ```
108
112
 
109
- if `command: ` properties are blank, the swipe/pinch doesn't trigger command.
113
+ if `command: ` properties are blank, the swipe/pinch doesn't execute command.
110
114
 
111
115
  `threshold:` is sensitivity to swipe/pinch. Default value is 1.
112
116
  If the swipe's threshold is `0.5`, shorten swipe-length by half.
@@ -147,6 +151,10 @@ swipe:
147
151
  2. Open `$ gnome-session-properties`
148
152
  3. Add Fusuma and input location where you checked above's path
149
153
 
154
+ ## Support
155
+
156
+ [![Patreon](https://c5.patreon.com/external/logo/become_a_patron_button.png)](https://www.patreon.com/iberianpig)
157
+
150
158
  ## Contributing
151
159
 
152
160
  Bug reports and pull requests are welcome on GitHub at https://github.com/iberianpig/fusuma. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
@@ -1,4 +1,4 @@
1
- lib = File.expand_path('../lib', __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
  require 'fusuma/version'
4
4
 
@@ -1,7 +1,7 @@
1
1
  require_relative 'fusuma/version'
2
- require_relative 'fusuma/action_stack'
3
- require_relative 'fusuma/gesture_action'
4
- require_relative 'fusuma/event_trigger'
2
+ require_relative 'fusuma/event_stack'
3
+ require_relative 'fusuma/gesture_event'
4
+ require_relative 'fusuma/command_executor'
5
5
  require_relative 'fusuma/swipe.rb'
6
6
  require_relative 'fusuma/pinch.rb'
7
7
  require_relative 'fusuma/multi_logger'
@@ -68,14 +68,16 @@ module Fusuma
68
68
  end
69
69
  end
70
70
 
71
+ def initialize
72
+ @event_stack = EventStack.new
73
+ end
74
+
71
75
  def run
72
76
  LibinputCommands.new.debug_events do |line|
73
- gesture_action = GestureAction.initialize_by(line, Device.ids)
74
- next if gesture_action.nil?
75
- @action_stack ||= ActionStack.new
76
- @action_stack << gesture_action
77
- event_trigger = @action_stack.generate_event_trigger
78
- event_trigger.exec_command unless event_trigger.nil?
77
+ gesture_event = GestureEvent.initialize_by(line, Device.ids)
78
+ next unless gesture_event
79
+ @event_stack << gesture_event
80
+ @event_stack.generate_command_executor.tap { |c| c.execute if c }
79
81
  end
80
82
  end
81
83
  end
@@ -0,0 +1,34 @@
1
+ module Fusuma
2
+ # Execute Command
3
+ class CommandExecutor
4
+ def initialize(finger, vector)
5
+ @finger = finger.to_i
6
+ @direction = vector.direction
7
+ @event_type = vector.class::TYPE
8
+ end
9
+ attr_reader :finger, :direction, :event_type
10
+
11
+ def execute
12
+ `#{command_or_shortcut}`
13
+ MultiLogger.info("Execute: #{command_or_shortcut}")
14
+ end
15
+
16
+ private
17
+
18
+ def command_or_shortcut
19
+ @command_or_shortcut ||= command || shortcut || no_command
20
+ end
21
+
22
+ def command
23
+ Config.command(self)
24
+ end
25
+
26
+ def shortcut
27
+ Config.shortcut(self).tap { |s| return "xdotool key #{s}" if s }
28
+ end
29
+
30
+ def no_command
31
+ 'echo "Command is not assigned"'
32
+ end
33
+ end
34
+ end
@@ -6,20 +6,20 @@ module Fusuma
6
6
  include Singleton
7
7
 
8
8
  class << self
9
- def command(event_trigger)
10
- instance.command(event_trigger)
9
+ def command(command_executor)
10
+ instance.command(command_executor)
11
11
  end
12
12
 
13
- def shortcut(event_trigger)
14
- instance.shortcut(event_trigger)
13
+ def shortcut(command_executor)
14
+ instance.shortcut(command_executor)
15
15
  end
16
16
 
17
- def threshold(action_type)
18
- instance.threshold(action_type)
17
+ def threshold(command_executor)
18
+ instance.threshold(command_executor)
19
19
  end
20
20
 
21
- def interval(action_type)
22
- instance.interval(action_type)
21
+ def interval(command_executor)
22
+ instance.interval(command_executor)
23
23
  end
24
24
 
25
25
  def reload
@@ -31,7 +31,7 @@ module Fusuma
31
31
  attr_accessor :custom_path
32
32
 
33
33
  def initialize
34
- @custom_path = nil
34
+ self.custom_path = nil
35
35
  reload
36
36
  end
37
37
 
@@ -41,28 +41,36 @@ module Fusuma
41
41
  self
42
42
  end
43
43
 
44
- def command(event_trigger)
45
- seek_index = [*action_index(event_trigger), 'command']
46
- cache(seek_index) { search_config(keymap, seek_index) }
44
+ def command(command_executor)
45
+ seek_index = [*event_index(command_executor), 'command']
46
+ search_config_cached(seek_index)
47
47
  end
48
48
 
49
- def shortcut(event_trigger)
50
- seek_index = [*action_index(event_trigger), 'shortcut']
51
- cache(seek_index) { search_config(keymap, seek_index) }
49
+ def shortcut(command_executor)
50
+ seek_index = [*event_index(command_executor), 'shortcut']
51
+ search_config_cached(seek_index)
52
52
  end
53
53
 
54
- def threshold(action_type)
55
- seek_index = ['threshold', action_type]
56
- cache(seek_index) { search_config(keymap, seek_index) } || 1
54
+ def threshold(command_executor)
55
+ seek_index_specific = [*event_index(command_executor), 'threshold']
56
+ seek_index_global = ['threshold', command_executor.event_type]
57
+ search_config_cached(seek_index_specific) ||
58
+ search_config_cached(seek_index_global) || 1
57
59
  end
58
60
 
59
- def interval(action_type)
60
- seek_index = ['interval', action_type]
61
- cache(seek_index) { search_config(keymap, seek_index) } || 1
61
+ def interval(command_executor)
62
+ seek_index_specific = [*event_index(command_executor), 'interval']
63
+ seek_index_global = ['interval', command_executor.event_type]
64
+ search_config_cached(seek_index_specific) ||
65
+ search_config_cached(seek_index_global) || 1
62
66
  end
63
67
 
64
68
  private
65
69
 
70
+ def search_config_cached(seek_index)
71
+ cache(seek_index) { search_config(keymap, seek_index) }
72
+ end
73
+
66
74
  def search_config(keymap_node, seek_index)
67
75
  if seek_index == []
68
76
  return nil if keymap_node.is_a? Hash
@@ -98,11 +106,11 @@ module Fusuma
98
106
  File.expand_path "../../#{filename}", __FILE__
99
107
  end
100
108
 
101
- def action_index(event_trigger)
102
- action_type = event_trigger.action_type
103
- finger = event_trigger.finger
104
- direction = event_trigger.direction
105
- [action_type, finger, direction]
109
+ def event_index(command_executor)
110
+ event_type = command_executor.event_type
111
+ finger = command_executor.finger
112
+ direction = command_executor.direction
113
+ [event_type, finger, direction]
106
114
  end
107
115
 
108
116
  def cache(key)
@@ -0,0 +1,87 @@
1
+ module Fusuma
2
+ # manage events and generate command
3
+ class EventStack < Array
4
+ ELAPSED_TIME = 0.01
5
+
6
+ def initialize(*args)
7
+ super(*args)
8
+ end
9
+
10
+ # @return [CommandExecutor, nil]
11
+ def generate_command_executor
12
+ return unless enough_events?
13
+ vector = generate_vector(detect_event_type)
14
+ trigger = CommandExecutor.new(finger, vector)
15
+ return unless vector.enough?(trigger)
16
+ clear
17
+ trigger
18
+ end
19
+
20
+ # @params [GestureEvent]
21
+ def push(gesture_event)
22
+ super(gesture_event)
23
+ clear if event_end?
24
+ end
25
+ alias << push
26
+
27
+ private
28
+
29
+ def generate_vector(event_type)
30
+ case event_type
31
+ when 'swipe'
32
+ avg_swipe
33
+ when 'pinch'
34
+ avg_pinch
35
+ end
36
+ end
37
+
38
+ def finger
39
+ last.finger
40
+ end
41
+
42
+ def avg_swipe
43
+ move_x = avg_attrs(:move_x)
44
+ move_y = avg_attrs(:move_y)
45
+ Swipe.new(move_x, move_y)
46
+ end
47
+
48
+ def avg_pinch
49
+ diameter = avg_attrs(:zoom)
50
+ delta_diameter = diameter - first.zoom
51
+ Pinch.new(delta_diameter)
52
+ end
53
+
54
+ def sum_attrs(attr)
55
+ send('map') do |gesture_event|
56
+ gesture_event.send(attr.to_sym.to_s)
57
+ end.compact.inject(:+)
58
+ end
59
+
60
+ def avg_attrs(attr)
61
+ sum_attrs(attr) / length
62
+ end
63
+
64
+ def event_end?
65
+ last_event_name =~ /_END$/
66
+ end
67
+
68
+ def last_event_name
69
+ return false if last.class != GestureEvent
70
+ last.event
71
+ end
72
+
73
+ def enough_events?
74
+ length > 2
75
+ end
76
+
77
+ def enough_elapsed_time?
78
+ return false if length.zero?
79
+ (last.time - first.time) > ELAPSED_TIME
80
+ end
81
+
82
+ def detect_event_type
83
+ first.event =~ /GESTURE_(.*?)_/
84
+ Regexp.last_match(1).downcase
85
+ end
86
+ end
87
+ end
@@ -1,15 +1,15 @@
1
1
  module Fusuma
2
- # pinch or swipe action
3
- class GestureAction
4
- def initialize(time, action, finger, directions)
5
- @time = time.to_f
6
- @action = action
2
+ # pinch or swipe or rotate event
3
+ class GestureEvent
4
+ def initialize(time, event, finger, directions)
5
+ @time = time.to_f
6
+ @event = event
7
7
  @finger = finger
8
8
  @move_x = directions[:move][:x].to_f
9
9
  @move_y = directions[:move][:y].to_f
10
10
  @zoom = directions[:zoom].to_f
11
11
  end
12
- attr_reader :time, :action, :finger,
12
+ attr_reader :time, :event, :finger,
13
13
  :move_x, :move_y, :zoom
14
14
 
15
15
  class << self
@@ -19,25 +19,25 @@ module Fusuma
19
19
  end
20
20
  return if line.to_s =~ /_BEGIN/
21
21
  return unless line.to_s =~ /GESTURE_SWIPE|GESTURE_PINCH/
22
- time, action, finger, directions = gesture_action_arguments(line)
23
- MultiLogger.debug(time: time, action: action,
22
+ time, event, finger, directions = gesture_event_arguments(line)
23
+ MultiLogger.debug(time: time, event: event,
24
24
  finger: finger, directions: directions)
25
- GestureAction.new(time, action, finger, directions)
25
+ GestureEvent.new(time, event, finger, directions)
26
26
  end
27
27
 
28
28
  private
29
29
 
30
- def gesture_action_arguments(libinput_line)
31
- action, time, finger, other = parse_libinput(libinput_line)
30
+ def gesture_event_arguments(libinput_line)
31
+ event, time, finger, other = parse_libinput(libinput_line)
32
32
  move_x, move_y, zoom = parse_finger_directions(other)
33
33
  directions = { move: { x: move_x, y: move_y }, zoom: zoom }
34
- [time, action, finger, directions]
34
+ [time, event, finger, directions]
35
35
  end
36
36
 
37
37
  def parse_libinput(line)
38
- _device, action, time, other = line.strip.split(nil, 4)
38
+ _device, event, time, other = line.strip.split(nil, 4)
39
39
  finger, other = other.split(nil, 2)
40
- [action, time, finger, other]
40
+ [event, time, finger, other]
41
41
  end
42
42
 
43
43
  def parse_finger_directions(line)
@@ -70,6 +70,7 @@ module Fusuma
70
70
  end
71
71
 
72
72
  private
73
+
73
74
  # use device option only if libinput detect only 1 device
74
75
  # @return [String]
75
76
  def device_option
@@ -1,6 +1,8 @@
1
1
  module Fusuma
2
2
  # vector data
3
3
  class Pinch
4
+ TYPE = 'pinch'.freeze
5
+
4
6
  BASE_THERESHOLD = 0.3
5
7
  BASE_INTERVAL = 0.05
6
8
 
@@ -15,33 +17,34 @@ module Fusuma
15
17
  'out'
16
18
  end
17
19
 
18
- def enough?
20
+ def enough?(trigger)
19
21
  MultiLogger.debug(diameter: diameter)
20
- enough_diameter? && enough_interval? && self.class.touch_last_time
22
+ enough_diameter?(trigger) && enough_interval?(trigger) &&
23
+ self.class.touch_last_time
21
24
  end
22
25
 
23
26
  private
24
27
 
25
- def enough_diameter?
26
- diameter.abs > threshold
28
+ def enough_diameter?(trigger)
29
+ diameter.abs > threshold(trigger)
27
30
  end
28
31
 
29
- def enough_interval?
32
+ def enough_interval?(trigger)
30
33
  return true if first_time?
31
- return true if (Time.now - self.class.last_time) > interval_time
34
+ return true if (Time.now - self.class.last_time) > interval_time(trigger)
32
35
  false
33
36
  end
34
37
 
35
38
  def first_time?
36
- self.class.last_time.nil?
39
+ !self.class.last_time
37
40
  end
38
41
 
39
- def threshold
40
- @threshold ||= BASE_THERESHOLD * Config.threshold('pinch')
42
+ def threshold(trigger)
43
+ @threshold ||= BASE_THERESHOLD * Config.threshold(trigger)
41
44
  end
42
45
 
43
- def interval_time
44
- @interval_time ||= BASE_INTERVAL * Config.interval('pinch')
46
+ def interval_time(trigger)
47
+ @interval_time ||= BASE_INTERVAL * Config.interval(trigger)
45
48
  end
46
49
 
47
50
  class << self
@@ -1,12 +1,14 @@
1
1
  module Fusuma
2
2
  # vector data
3
3
  class Swipe
4
+ TYPE = 'swipe'.freeze
5
+
4
6
  BASE_THERESHOLD = 20
5
7
  BASE_INTERVAL = 0.5
6
8
 
7
- def initialize(x, y)
8
- @x = x
9
- @y = y
9
+ def initialize(move_x, move_y)
10
+ @x = move_x
11
+ @y = move_y
10
12
  end
11
13
  attr_reader :x, :y
12
14
 
@@ -15,33 +17,35 @@ module Fusuma
15
17
  y > 0 ? 'down' : 'up'
16
18
  end
17
19
 
18
- def enough?
20
+ def enough?(trigger)
19
21
  MultiLogger.debug(x: x, y: y)
20
- enough_distance? && enough_interval? && self.class.touch_last_time
22
+ enough_distance?(trigger) && enough_interval?(trigger) &&
23
+ self.class.touch_last_time
21
24
  end
22
25
 
23
26
  private
24
27
 
25
- def enough_distance?
28
+ def enough_distance?(trigger)
29
+ threshold = threshold(trigger)
26
30
  (x.abs > threshold) || (y.abs > threshold)
27
31
  end
28
32
 
29
- def enough_interval?
33
+ def enough_interval?(trigger)
30
34
  return true if first_time?
31
- return true if (Time.now - self.class.last_time) > interval_time
35
+ return true if (Time.now - self.class.last_time) > interval_time(trigger)
32
36
  false
33
37
  end
34
38
 
35
39
  def first_time?
36
- self.class.last_time.nil?
40
+ !self.class.last_time
37
41
  end
38
42
 
39
- def threshold
40
- @threshold ||= BASE_THERESHOLD * Config.threshold('swipe')
43
+ def threshold(trigger)
44
+ @threshold ||= BASE_THERESHOLD * Config.threshold(trigger)
41
45
  end
42
46
 
43
- def interval_time
44
- @interval_time ||= BASE_INTERVAL * Config.interval('swipe')
47
+ def interval_time(trigger)
48
+ @interval_time ||= BASE_INTERVAL * Config.interval(trigger)
45
49
  end
46
50
 
47
51
  class << self
@@ -1,3 +1,3 @@
1
1
  module Fusuma
2
- VERSION = '0.9.2'.freeze
2
+ VERSION = '0.10.1'.freeze
3
3
  end
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: 0.9.2
4
+ version: 0.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - iberianpig
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-07-19 00:00:00.000000000 Z
11
+ date: 2018-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -118,14 +118,16 @@ executables:
118
118
  extensions: []
119
119
  extra_rdoc_files: []
120
120
  files:
121
+ - ".github/ISSUE_TEMPLATE/bug_report.md"
122
+ - ".github/ISSUE_TEMPLATE/feature_request.md"
121
123
  - ".github/stale.yml"
122
124
  - ".gitignore"
125
+ - ".reek.yml"
123
126
  - ".rspec"
124
127
  - ".rubocop.yml"
125
128
  - ".travis.yml"
126
129
  - CODE_OF_CONDUCT.md
127
130
  - Gemfile
128
- - ISSUE_TEMPLATE.md
129
131
  - LICENSE
130
132
  - README.md
131
133
  - Rakefile
@@ -134,12 +136,12 @@ files:
134
136
  - exe/fusuma
135
137
  - fusuma.gemspec
136
138
  - lib/fusuma.rb
137
- - lib/fusuma/action_stack.rb
139
+ - lib/fusuma/command_executor.rb
138
140
  - lib/fusuma/config.rb
139
141
  - lib/fusuma/config.yml
140
142
  - lib/fusuma/device.rb
141
- - lib/fusuma/event_trigger.rb
142
- - lib/fusuma/gesture_action.rb
143
+ - lib/fusuma/event_stack.rb
144
+ - lib/fusuma/gesture_event.rb
143
145
  - lib/fusuma/libinput_commands.rb
144
146
  - lib/fusuma/multi_logger.rb
145
147
  - lib/fusuma/pinch.rb
@@ -1,37 +0,0 @@
1
- <!--
2
-
3
- Have you read Fusuma's CODE_OF_CONDUCT.md? By filing an Issue, you are expected to comply with it, including treating everyone with respect: https://github.com/iberianpig/fusuma/blob/master/CODE_OF_CONDUCT.md
4
-
5
- -->
6
-
7
- ### Prerequisites
8
-
9
- * [ ] Put an X between the brackets on this line if you have done all of the following:
10
- * Read Documents. https://github.com/iberianpig/fusuma#installation
11
- * Checked that `libinput-debug-events` worked correctly.
12
- * Reproduced the problem in latest version. Update fusuma with `gem update fusuma`
13
- * Checked that your issue isn't already filed: https://github.com/iberianpig/fusuma/issues
14
-
15
- ### Description
16
-
17
- [Description of the issue]
18
-
19
- ### Steps to Reproduce
20
-
21
- 1. [First Step]
22
- 2. [Second Step]
23
- 3. [and so on...]
24
-
25
- **Expected behavior:** [What you expect to happen]
26
-
27
- **Actual behavior:** [What actually happens]
28
-
29
- **Reproduces how often:** [What percentage of the time does it reproduce?]
30
-
31
- ### Versions
32
-
33
- You can get this information from copy and pasting the output of `fusuma --version` from the command line. Also, please include the OS and what version of the OS you're running.
34
-
35
- ### Additional Information
36
-
37
- Any additional information, your `~/.config/fusuma/config.yml` or data that might be necessary to reproduce the issue.
@@ -1,97 +0,0 @@
1
- module Fusuma
2
- # manage actions
3
- class ActionStack < Array
4
- ELAPSED_TIME = 0.01
5
-
6
- def initialize(*args)
7
- super(*args)
8
- end
9
-
10
- def generate_event_trigger
11
- return unless enough_actions?
12
- action_type = detect_action_type
13
- direction = detect_direction(action_type)
14
- return if direction.nil?
15
- @last_triggered_time = last.time
16
- finger = detect_finger
17
- clear
18
- EventTrigger.new(finger, direction, action_type)
19
- end
20
-
21
- def push(gesture_action)
22
- super(gesture_action)
23
- clear if action_end?
24
- end
25
- alias << push
26
-
27
- private
28
-
29
- def detect_direction(action_type)
30
- vector = generate_vector(action_type)
31
- return if vector && !vector.enough?
32
- vector.direction
33
- end
34
-
35
- def generate_vector(action_type)
36
- case action_type
37
- when 'swipe'
38
- avg_swipe
39
- when 'pinch'
40
- avg_pinch
41
- end
42
- end
43
-
44
- def detect_finger
45
- last.finger
46
- end
47
-
48
- def avg_swipe
49
- move_x = avg_attrs(:move_x)
50
- move_y = avg_attrs(:move_y)
51
- Swipe.new(move_x, move_y)
52
- end
53
-
54
- def avg_pinch
55
- diameter = avg_attrs(:zoom)
56
- delta_diameter = diameter - first.zoom
57
- Pinch.new(delta_diameter)
58
- end
59
-
60
- def sum_attrs(attr)
61
- send('map') do |gesture_action|
62
- gesture_action.send(attr.to_sym.to_s)
63
- end.compact.inject(:+)
64
- end
65
-
66
- def avg_attrs(attr)
67
- sum_attrs(attr) / length
68
- end
69
-
70
- def action_end?
71
- last_action_name =~ /_END$/
72
- end
73
-
74
- def last_action_name
75
- return false if last.class != GestureAction
76
- last.action
77
- end
78
-
79
- def enough_actions?
80
- length > 2
81
- end
82
-
83
- def enough_elapsed_time?
84
- return false if length.zero?
85
- (last.time - first.time) > ELAPSED_TIME
86
- end
87
-
88
- def last_triggered_time
89
- @last_triggered_time ||= 0
90
- end
91
-
92
- def detect_action_type
93
- first.action =~ /GESTURE_(.*?)_/
94
- Regexp.last_match(1).downcase
95
- end
96
- end
97
- end
@@ -1,24 +0,0 @@
1
- module Fusuma
2
- # manage actions
3
- class EventTrigger
4
- def initialize(finger, direction, action_type)
5
- @finger = finger.to_i
6
- @direction = direction
7
- @action_type = action_type
8
- end
9
- attr_reader :finger, :direction, :action_type
10
-
11
- def exec_command
12
- return if command.nil?
13
- `#{command}`
14
- MultiLogger.info("trigger event: #{command}")
15
- end
16
-
17
- private
18
-
19
- def command
20
- Config.command(self).tap { |c| return c if c }
21
- Config.shortcut(self).tap { |s| return "xdotool key #{s}" if s }
22
- end
23
- end
24
- end