Skip to content

Commit

Permalink
refactor: Update touch_state handling in touchpad remapper
Browse files Browse the repository at this point in the history
  • Loading branch information
iberianpig committed Mar 20, 2024
1 parent 536e26d commit 16f0191
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 69 deletions.
26 changes: 17 additions & 9 deletions lib/fusuma/plugin/inputs/remap_touchpad_input.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,24 @@ def read_from_io

gesture = "touch"
finger = data["finger"]
status = case data["status"]
when 0
"end"
when 1
"begin"
# when 2 # TODO: support update
# "update"
end

Events::Records::GestureRecord.new(status: status, gesture: gesture, finger: finger, delta: nil)
# @touch_state ||= {}
# @mt_slot ||= 0
# @touch_state[@mt_slot] ||= {
# MT_TRACKING_ID: nil,
# X: nil,
# Y: nil,
# valid_touch_point: false
# }
# TODO: implement update touch_state
status =
if data["touch_state"].any? { |_, v| v["valid_touch_point"] }
"begin"
else
"end"
end

Events::Records::GestureRecord.new(gesture: gesture, status: status, finger: finger, delta: nil)
end

private
Expand Down
10 changes: 6 additions & 4 deletions lib/fusuma/plugin/remap/keyboard_remapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def run
grab_keyboards

old_ie = nil
layer = nil
next_mapping = nil
current_mapping = {}

Expand All @@ -40,11 +41,12 @@ def run
io = ios.first.first

if io == @layer_manager.reader
@layer_manager.receive_layer
layer = @layer_manager.receive_layer # update @current_layer
if layer.nil?
next
end

MultiLogger.debug "Remapper#run: layer changed to #{@layer_manager.current_layer}"
next_mapping = @layer_manager.find_mapping
MultiLogger.debug "Remapper#run: next_mapping: #{next_mapping}"
next_mapping = @layer_manager.find_mapping(layer)
next
end

Expand Down
26 changes: 16 additions & 10 deletions lib/fusuma/plugin/remap/layer_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,27 @@ def initialize
@layers = {}
@reader, @writer = IO.pipe
@current_layer = {} # preserve order
@last_layer = nil
@last_remove = nil
end

# @param [Hash] layer
# @param [Boolean] remove
def send_layer(layer:, remove: false)
return if @last_layer == layer && @last_remove == remove
return if (@last_layer == layer) && (@last_remove == remove)

@last_layer = layer
@last_remove = remove
@writer.write({layer: layer, remove: remove}.to_msgpack)
end

# Read layer from pipe and return remap layer
# Read layer from pipe and update @current_layer
# @return [Hash] current layer
# @example
# @return [Hash]
# receive_layer
# # => { thumbsense: true }
# receive_layer
# # => { thumbsense: true, application: "Google-chrome" }
def receive_layer
@layer_unpacker ||= MessagePack::Unpacker.new(@reader)

Expand All @@ -40,28 +46,28 @@ def receive_layer
layer = data[:layer] # e.g { thumbsense: true }
remove = data[:remove] # e.g true

# update @current_layer
if remove
@current_layer.delete_if { |k, _v| layer.key?(k) }
else
# If duplicate keys exist, order of keys is preserved
@current_layer.merge!(layer)
end
@current_layer
end

# Find remap layer from config
# @param [Hash] layer
# @return [Hash]
def find_mapping(layer = @current_layer)
# @return [Hash] remap layer
def find_mapping(layer)
@layers[layer] ||= begin
result = nil
_ = Fusuma::Config::Searcher.find_context(layer) {
_ = Fusuma::Config::Searcher.find_context(layer) do
result = Fusuma::Config.search(Fusuma::Config::Index.new(:remap))
next unless result

result = result.deep_transform_keys do |key|
key.upcase.to_sym
end
}
result = result.deep_transform_keys { |key| key.upcase.to_sym }
end

result || {}
end
Expand Down
76 changes: 30 additions & 46 deletions lib/fusuma/plugin/remap/touchpad_remapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ def initialize(fusuma_writer:, source_touchpad:)
# send remapped events to virtual touchpad or virtual mouse
def run
create_virtual_touchpad

touch_state = {}
mt_slot = 0
finger_state = nil
loop do
IO.select([@source_touchpad.file]) # , @layer_manager.reader])

Expand All @@ -47,33 +51,24 @@ def run
# Event: time 1698456258.382693, -------------- SYN_REPORT ------------
input_event = @source_touchpad.read_input_event

@touch_state ||= {}
@mt_slot ||= 0
@touch_state[@mt_slot] ||= {
MT_TRACKING_ID: nil,
X: nil,
Y: nil,
valid_touch_point: false
}
@finger_state ||= nil
@syn_report = nil
@button_touch ||= nil
touch_state[mt_slot] ||= {MT_TRACKING_ID: nil, X: nil, Y: nil, valid_touch_point: false}
syn_report = nil

case input_event.type
when Revdev::EV_ABS
case input_event.code
when Revdev::ABS_MT_SLOT
@mt_slot = input_event.value
@touch_state[@mt_slot] ||= {}
mt_slot = input_event.value
touch_state[mt_slot] ||= {}
when Revdev::ABS_MT_TRACKING_ID
@touch_state[@mt_slot][:MT_TRACKING_ID] = input_event.value
touch_state[mt_slot][:MT_TRACKING_ID] = input_event.value
if input_event.value == -1
@touch_state[@mt_slot] = {}
touch_state[mt_slot] = {}
end
when Revdev::ABS_MT_POSITION_X
@touch_state[@mt_slot][:X] = input_event.value
touch_state[mt_slot][:X] = input_event.value
when Revdev::ABS_MT_POSITION_Y
@touch_state[@mt_slot][:Y] = input_event.value
touch_state[mt_slot][:Y] = input_event.value
when Revdev::ABS_X, Revdev::ABS_Y
# ignore
when Revdev::ABS_MT_PRESSURE
Expand All @@ -88,57 +83,46 @@ def run
when Revdev::BTN_TOUCH
# ignore
when Revdev::BTN_TOOL_FINGER
@finger_state = (input_event.value == 1) ? 1 : nil
finger_state = (input_event.value == 1) ? 1 : 0
when Revdev::BTN_TOOL_DOUBLETAP
@finger_state = (input_event.value == 1) ? 2 : nil
finger_state = (input_event.value == 1) ? 2 : 1
when Revdev::BTN_TOOL_TRIPLETAP
@finger_state = (input_event.value == 1) ? 3 : nil
finger_state = (input_event.value == 1) ? 3 : 2
when Revdev::BTN_TOOL_QUADTAP
@finger_state = (input_event.value == 1) ? 4 : nil
finger_state = (input_event.value == 1) ? 4 : 3
when 0x148 # define BTN_TOOL_QUINTTAP 0x148 /* Five fingers on trackpad */
@finger_state = (input_event.value == 1) ? 5 : nil
finger_state = (input_event.value == 1) ? 5 : 4
end
when Revdev::EV_MSC
case input_event.code
when 0x05 # define MSC_TIMESTAMP 0x05
@current_timestamp = input_event.value
# ignore
# current_timestamp = input_event.value
end
when Revdev::EV_SYN
case input_event.code
when Revdev::SYN_REPORT
@syn_report = input_event.value
syn_report = input_event.value
when Revdev::SYN_DROPPED
MultiLogger.error "Dropped: #{input_event.value}"
else
raise "unhandled event"
raise "unhandled event", "#{input_event.hr_type}, #{input_event.hr_code}, #{input_event.value}"
end
else
pp [input_event.hr_type, input_event.hr_code, input_event.value]
raise "unhandled event"
raise "unhandled event", "#{input_event.hr_type}, #{input_event.hr_code}, #{input_event.value}"
end

# TODO:
# Remember the most recent valid touch position and exclude it if it is close to that position
# For example, when dragging, it is possible to touch around the edge of the touchpad again after reaching the edge of the touchpad, so in that case, you do not want to execute palm detection
if @touch_state[@mt_slot][:valid_touch_point] != true
@touch_state[@mt_slot][:valid_touch_point] = @palm_detector.palm?(@touch_state[@mt_slot])
if touch_state[mt_slot][:valid_touch_point] != true
touch_state[mt_slot][:valid_touch_point] = @palm_detector.palm?(touch_state[mt_slot])
end

if @syn_report
@syn_report = nil

# TODO: refactor Thumbsense specific logic: Event suppression
@status = if @touch_state.any? { |k, v| v[:valid_touch_point] }
1
else
0
end

# TODO: send begin/update/end events
# Send events only when status changes from 0 to 1 or from 1 to 0
if @status != @prev_status
@prev_status = @status
data = {status: @status, finger: @finger_state, touch_state: @touch_state}
@fusuma_writer.write(data.to_msgpack)
end
if syn_report
# TODO: define format as fusuma_input
data = {finger: finger_state, touch_state: touch_state}
@fusuma_writer.write(data.to_msgpack)
end
end
end
Expand Down

0 comments on commit 16f0191

Please sign in to comment.