Created
August 15, 2022 17:14
-
-
Save james2doyle/7ba8dca41b23a6a227a6568907a1ee96 to your computer and use it in GitHub Desktop.
A Hammerspoon script that allows actions to be bound to quadrants on the trackpad
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
Name: Touchpad Control | |
Author: James Doyle <james2doyle@gmail.com> | |
Description: Hook into events/gestures that are triggered on the trackpad | |
Installation: Just require this file in your Hammerspoon init.lua file | |
Usage: | |
Bind the click actions or swipe actions to events | |
]]-- | |
local trackpad_actions = {} | |
trackpad_actions["double_click"] = {} | |
trackpad_actions["triple_click"] = { | |
top_left = { mod = { "cmd" }, press = "w", name = "close window" }, | |
bottom_left = { mod = { "cmd" }, press = "m", name = "minimize window" } | |
} | |
trackpad_actions["swipe"] = { | |
{ | |
start = "top_left", | |
stop = "bottom_left", | |
name = "decrease volume", | |
action = function() | |
local audio_output = hs.audiodevice.defaultOutputDevice() | |
local volume = audio_output:outputVolume() | |
audio_output:setOutputVolume(volume - 5.0) | |
end | |
}, | |
{ | |
start = "bottom_left", | |
stop = "top_left", | |
name = "increase volume", | |
action = function() | |
local audio_output = hs.audiodevice.defaultOutputDevice() | |
local volume = audio_output:outputVolume() | |
audio_output:setOutputVolume(volume + 5.0) | |
end | |
} | |
} | |
-- trackpad layout | |
-- |0,1 1,1| | |
-- | | | |
-- | | | |
-- | 0.5,0.5 | | |
-- | | | |
-- | | | |
-- |0,0 1,0| | |
local log = hs.logger.new('trackpad-module', 'debug') | |
log:d("i am debugging trackpad-module") | |
local top_left = { start = { x = 0, y = 0.75 }, stop = { x = 0.25, y = 1 } } | |
local top_right = { start = { x = 0.75, y = 0.75 }, stop = { x = 1, y = 1 } } | |
local bottom_left = { start = { x = 0, y = 0 }, stop = { x = 0.25, y = 0.25 } } | |
local bottom_right = { start = { x = 0.75, y = 0 }, stop = { x = 1, y = 0.75 } } | |
-- causes eventtap to respond to *all* events that it can, except keyboard stuff | |
local eventList = { | |
"all", | |
hs.eventtap.event.types.flagsChanged, | |
hs.eventtap.event.types.keyDown, | |
hs.eventtap.event.types.keyUp, | |
hs.eventtap.event.types.mouseMoved | |
} | |
local lastEvent = nil | |
local click_counter = 0 | |
local start_quadrant = nil | |
local end_quadrant = nil | |
-- debounce the callback that is run after touching is complete | |
local timer = hs.timer.doAfter(0.2, function() | |
if start_quadrant ~= nil and end_quadrant ~= nil then | |
hs.fnutils.each(trackpad_actions.swipe, function (action) | |
if start_quadrant == action.start and end_quadrant == action.stop then | |
log:d("swipe, " .. action.name) | |
action.action() | |
end | |
end) | |
if click_counter == 2 then | |
for quadrant,action in hs.fnutils.sortByKeys(trackpad_actions.double_click) do | |
if start_quadrant == quadrant and end_quadrant == quadrant then | |
log:d("double_click, " .. action.name) | |
hs.eventtap.keyStroke(action.mod, action.press) | |
end | |
end | |
end | |
if click_counter == 3 then | |
for quadrant,action in hs.fnutils.sortByKeys(trackpad_actions.triple_click) do | |
if start_quadrant == quadrant and end_quadrant == quadrant then | |
log:d("triple_click, " .. action.name) | |
hs.eventtap.keyStroke(action.mod, action.press) | |
end | |
end | |
end | |
click_counter = 0 | |
start_quadrant = nil | |
end_quadrant = nil | |
end | |
end):stop() | |
function get_position(x, y) | |
if x > top_left.start.x and y > top_left.start.y and x < top_left.stop.x and y < top_left.stop.y then | |
return "top_left" | |
end | |
if x > top_right.start.x and y > top_right.start.y and x < top_right.stop.x and y < top_right.stop.y then | |
return "top_right" | |
end | |
if x > bottom_left.start.x and y > bottom_left.start.y and x < bottom_left.stop.x and y < bottom_left.stop.y then | |
return "bottom_left" | |
end | |
if x > bottom_right.start.x and y > bottom_right.start.y and x < bottom_right.stop.x and y < bottom_right.stop.y then | |
return "bottom_right" | |
end | |
return "center" | |
end | |
hs.eventtap.new({hs.eventtap.event.types.gesture, hs.eventtap.event.types.tabletPointer}, function (e) | |
local details = e:getTouches() | |
if details[1] and details[1]["phase"] == "began" then | |
click_counter = click_counter + 1 | |
end | |
if start_quadrant == nil and details[1] and details[1]["phase"] == "began" then | |
local x = details[1]["normalizedPosition"]["x"] | |
local y = details[1]["normalizedPosition"]["y"] | |
start_quadrant = get_position(x, y) | |
end | |
if end_quadrant == nil and details[1] and details[1]["phase"] == "ended" then | |
local x = details[1]["normalizedPosition"]["x"] | |
local y = details[1]["normalizedPosition"]["y"] | |
end_quadrant = get_position(x, y) | |
end | |
timer:stop() | |
timer:start() | |
end):start() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment