fusuma 0.9.2 → 0.10.1

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.
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