Skip to content

Commit

Permalink
Merge pull request #3 from iberianpig/feature/remap-pointer
Browse files Browse the repository at this point in the history
Integrate Fusuma-plugin-remap into Detector
  • Loading branch information
iberianpig authored Apr 15, 2024
2 parents 91112fb + 13f82f1 commit 4524619
Show file tree
Hide file tree
Showing 10 changed files with 182 additions and 322 deletions.
4 changes: 2 additions & 2 deletions fusuma-plugin-thumbsense.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ Gem::Specification.new do |spec|
# https://packages.ubuntu.com/search?keywords=ruby&searchon=names&exact=1&suite=all&section=main
# support focal (20.04LTS) 2.7
spec.add_dependency "fusuma", ">= 3.2"
spec.add_dependency "fusuma-plugin-keypress", ">= 0.5"
spec.add_dependency "fusuma-plugin-remap"
spec.add_dependency "fusuma-plugin-keypress", ">= 0.11"
spec.add_dependency "fusuma-plugin-remap", ">= 0.4"
spec.metadata = {
"rubygems_mfa_required" => "true"
}
Expand Down
5 changes: 2 additions & 3 deletions lib/fusuma/plugin/buffers/thumbsense_buffer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Plugin
module Buffers
# manage events and generate command
class ThumbsenseBuffer < Buffer
DEFAULT_SOURCE = "thumbsense_parser"
DEFAULT_SOURCE = "remap_touchpad_input"

def config_param_types
{
Expand All @@ -20,8 +20,7 @@ def clear_expired(*)
# skip palm/begin record
return if !ended?(@events.last)

released_finger = @events.last.record.finger
@events.delete_if { |e| e.record.finger == released_finger }
clear
end

# @param event [Event]
Expand Down
4 changes: 4 additions & 0 deletions lib/fusuma/plugin/buffers/thumbsense_buffer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
plugin:
buffers:
thumbsense_buffer:
source: remap_touchpad_input
131 changes: 76 additions & 55 deletions lib/fusuma/plugin/detectors/thumbsense_detector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ module Plugin
module Detectors
# Detect Thumbsense context and change remap layer of fusuma-plugin-remap
class ThumbsenseDetector < Detector
# keypress buffer is used to detect modifier keys
SOURCES = %w[thumbsense keypress].freeze
BUFFER_TYPE = "thumbsense"

MODIFIER_KEYS = Set.new(%w[
CAPSLOCK
Expand All @@ -28,51 +28,74 @@ class ThumbsenseDetector < Detector
LAYER_CONTEXT = {thumbsense: true}.freeze

# Detect Context event and change remap layer of fusuma-plugin-remap
# @param buffers [Array<Buffer>]
# @param buffers [Array<Buffer>] ThumbsenseBuffer, KeypressBuffer
# @return [Event] if Thumbsense context is detected
# @return [Array<Event>] if Thumbsense context and Remap index when keypress is detected
# @return [NilClass] if event is NOT detected
def detect(buffers)
thumbsense_buffer = buffers.find { |b| b.type == BUFFER_TYPE }

return if thumbsense_buffer.empty?

MultiLogger.debug("thumbsense_buffer: #{thumbsense_buffer.events.map(&:record).map { |r| "#{r.finger} #{r.gesture} #{r.status}" }}")
@thumbsense_buffer ||= find_buffer(buffers, "thumbsense")
@keypress_buffer ||= find_buffer(buffers, "keypress")

layer_manager = Fusuma::Plugin::Remap::LayerManager.instance

if touch_released?(thumbsense_buffer)
# layer is thumbsense => create thumbsense context and remap index
# touch is touching => create thumbsense context and remap index
# touch is released => remove thumbsense context
# keypress -> touch => remove thumbsense context
if touch_released? && !thumbsense_layer?
MultiLogger.debug("thumbsense layer removed")
layer_manager.send_layer(layer: LAYER_CONTEXT, remove: true)
return
end

keypress_buffer = buffers.find { |b| b.type == "keypress" }
# When keypress event is first:
# If current layer is thumbsense, the layer should not be changed
# If current layer is not thumbsense, it should remain a normal key
# In other words, if the key event comes first, do nothing
if keypress_first?
MultiLogger.debug("keypress event is first")

# If only modifier keys are pressed or no key is pressed
if pressed_codes(keypress_buffer).all? { |code| MODIFIER_KEYS.include?(code) }

# Even if the palm is detected, keep the thumbsense layer until `:end` event
if palm_detected?(thumbsense_buffer)
layer_manager.send_layer(layer: LAYER_CONTEXT, remove: true)
return
end
return
end

layer_manager.send_layer(layer: LAYER_CONTEXT)
MultiLogger.debug("thumbsense context created") unless thumbsense_layer?
layer_manager.send_layer(layer: LAYER_CONTEXT)

# create thumbsense context
record = Events::Records::ContextRecord.new(
# create thumbsense context
context = create_event(
record: Events::Records::ContextRecord.new(
name: :thumbsense,
value: true
)
return create_event(record: record)
)

# TODO: Threshold
# create remap index
index = if (keys = pressed_codes) && !keys.empty?
MultiLogger.debug("thumbsense remap index created: #{keys}")
combined_keys = keys.join("+")
create_event(
record: Events::Records::IndexRecord.new(
index: Config::Index.new([:remap, combined_keys])
)
)
end

nil
[context, index].compact
end

private

def pressed_codes(keypress_buffer)
records = keypress_buffer.events.map(&:record)
# @param buffers [Array<Buffer>]
# @param type [String]
# @return [Buffer]
def find_buffer(buffers, type)
buffers.find { |b| b.type == type }
end

# @return [Array<String>]
def pressed_codes
records = @keypress_buffer.events.map(&:record)
codes = []
records.each do |r|
if r.status == "pressed"
Expand All @@ -84,45 +107,43 @@ def pressed_codes(keypress_buffer)
codes
end

def touching?(thumbsense_buffer)
!touch_released?(thumbsense_buffer)
# @return [TrueClass, FalseClass]
def touching?
!touch_released?(@thumbsense_buffer)
end

# @return [TrueClass, FalseClass]
def touch_released?(thumbsense_buffer)
thumbsense_events = thumbsense_buffer.events
touch_num = thumbsense_events.count { |e| (e.record.status == "begin") }
release_num = thumbsense_events.count { |e| e.record.status == "end" }
def touch_released?
return true if @thumbsense_buffer.empty?

touch_num <= release_num
@thumbsense_buffer.events.map(&:record).last&.status == "end"
end

# Detect palm, except when there is another touch
# @param thumbsense_buffer [Buffer]
# @return [TrueClass, FalseClass]
def palm_detected?(thumbsense_buffer)
# finger is a number to distinguish different touches and palms
# If the count remains, it is judged as a touch state
touch_state_per_finger = {}
thumbsense_buffer.events.each do |e|
f = e.record.finger
touch_state_per_finger[f] ||= 0

case e.record.status
when "begin"
touch_state_per_finger[f] += 1
when "palm"
if touch_state_per_finger[f] < 0
# NOTE: If Palm continues, it is equivalent to end
touch_state_per_finger[f] = 0
else
touch_state_per_finger[f] -= 1
end
when "end"
touch_state_per_finger[f] = 0
end
def thumbsense_layer?
return if @keypress_buffer.empty?

last_keypress = @keypress_buffer.events.last.record
return if last_keypress.status == "released"

current_layer = last_keypress&.layer
current_layer && current_layer["thumbsense"]
end

# Check if keypress event is first, before thumbsense event
# If last keypress event is modifier key, return false
# @param keypress_buffer [Buffer]
# @param thumbsense_buffer [Buffer]
# @return [TrueClass] if keypress event is first
# @return [FalseClass] if keypress event is NOT first or buffers are empty
def keypress_first?
return false if @thumbsense_buffer.empty? || @keypress_buffer.empty?

if (keys = pressed_codes) && !keys.empty?
return false if MODIFIER_KEYS.include?(keys.first)
end
touch_state_per_finger.values.all? { |count| count <= 0 }

@keypress_buffer.events.first.time < @thumbsense_buffer.events.first.time
end
end
end
Expand Down
27 changes: 0 additions & 27 deletions lib/fusuma/plugin/filters/thumbsense_filter.rb

This file was deleted.

5 changes: 0 additions & 5 deletions lib/fusuma/plugin/filters/thumbsense_filter.yml

This file was deleted.

50 changes: 0 additions & 50 deletions lib/fusuma/plugin/parsers/thumbsense_parser.rb

This file was deleted.

2 changes: 1 addition & 1 deletion spec/fusuma/plugin/buffers/thumbsense_buffer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ module Buffers
@buffer = ThumbsenseBuffer.new
@event_generator = lambda { |time = nil, finger = 1, status = "begin"|
Events::Event.new(time: time,
tag: "thumbsense_parser",
tag: "remap_touchpad_input",
record: Events::Records::GestureRecord.new(
status: status,
gesture: "thumbsense",
Expand Down
Loading

0 comments on commit 4524619

Please sign in to comment.