Add mouse-keyboard via hammerspoon

main
Steffen Rademacker 3 years ago
parent cc3daf4dfb
commit 95d1571e1b

@ -1,4 +1,5 @@
local tiling = require 'hs.tiling'
local vimouse = require('vimouse')
local appliaction = require 'hs.application'
local hyper = { 'cmd', 'alt', 'shift', 'ctrl' }
@ -38,6 +39,9 @@ local function fullsize(window)
window:setFrame(frame)
end
-- Move and click mouse via keyboard
vimouse(hyper, 'm')
hs.hotkey.bind(hyper, 'f', function() tiling.toggleFloat(fullsize); moveMouse() end)
hs.hotkey.bind(hyper, 'r', function() tiling.retile(); moveMouse() end)
hs.hotkey.bind(hyper, 'a', function() tiling.cycle(1); moveMouse() end)

@ -0,0 +1,194 @@
-- Save to ~/.hammerspoon
-- In ~/.hammerspoon/init.lua:
-- local vimouse = require('vimouse')
-- vimouse('cmd', 'm')
--
-- This sets cmd-m as the key that toggles Vi Mouse.
--
-- h/j/k/l moves the mouse cursor by 20 pixels. Holding shift moves by 100
-- pixels, and holding alt moves by 5 pixels.
--
-- Pressing <space> sends left mouse down. Releasing <space> sends left mouse
-- up. Holding <space> and pressing h/j/k/l is mouse dragging. Tapping
-- <space> quickly sends double and triple clicks. Holding ctrl sends right
-- mouse events.
--
-- <c-y> and <c-e> sends the scroll wheel event. Holding the keys will speed
-- up the scrolling.
--
-- Press <esc> or the configured toggle key to end Vi Mouse mode.
return function(tmod, tkey)
-- local overlay = nil
local log = hs.logger.new('vimouse', 'debug')
local tap = nil
local orig_coords = nil
local dragging = false
local scrolling = 0
local mousedown_time = 0
local mousepress_time = 0
local mousepress = 0
local tapmods = {['cmd']=false, ['ctrl']=false, ['alt']=false, ['shift']=false}
if type(tmod) == 'string' then
tapmods[tmod] = true
else
for _, name in ipairs(tmod) do
tapmods[name] = true
end
end
local eventTypes = hs.eventtap.event.types
local eventPropTypes = hs.eventtap.event.properties
local keycodes = hs.keycodes.map
function postEvent(et, coords, modkeys, clicks)
local e = hs.eventtap.event.newMouseEvent(et, coords, modkeys)
if clicks > 3 then
clicks = 3
end
e:setProperty(eventPropTypes.mouseEventClickState, clicks)
e:post()
end
tap = hs.eventtap.new({eventTypes.keyDown, eventTypes.keyUp}, function(event)
local code = event:getKeyCode()
local flags = event:getFlags()
local repeating = event:getProperty(eventPropTypes.keyboardEventAutorepeat)
local coords = hs.mouse.getAbsolutePosition()
if (code == keycodes.tab or code == keycodes['`']) and flags.cmd then
-- Window cycling
return false
end
if code == keycodes.space then
-- Mouse clicking
if repeating ~= 0 then
return true
end
local btn = 'left'
if flags.ctrl then
btn = 'right'
end
local now = hs.timer.secondsSinceEpoch()
if now - mousepress_time > hs.eventtap.doubleClickInterval() then
mousepress = 1
end
if event:getType() == eventTypes.keyUp then
dragging = false
postEvent(eventTypes[btn..'MouseUp'], coords, flags, mousepress)
elseif event:getType() == eventTypes.keyDown then
dragging = true
if now - mousedown_time <= 0.3 then
mousepress = mousepress + 1
mousepress_time = now
end
mousedown_time = hs.timer.secondsSinceEpoch()
postEvent(eventTypes[btn..'MouseDown'], coords, flags, mousepress)
end
orig_coords = coords
elseif event:getType() == eventTypes.keyDown then
local mul = 0
local step = 20
local x_delta = 0
local y_delta = 0
local scroll_y_delta = 0
local is_tapkey = code == keycodes[tkey]
if is_tapkey == true then
for name, _ in pairs(tapmods) do
if flags[name] == nil then
flags[name] = false
end
if tapmods[name] ~= flags[name] then
is_tapkey = false
break
end
end
end
if flags.alt then
step = 5
end
if flags.shift then
mul = 5
else
mul = 1
end
if is_tapkey or code == keycodes['escape'] then
if dragging then
postEvent(eventTypes.leftMouseUp, coords, flags, 0)
end
dragging = false
-- overlay:delete()
-- overlay = nil
hs.alert('Vi Mouse Off')
tap:stop()
hs.mouse.setAbsolutePosition(orig_coords)
return true
elseif (code == keycodes['y'] or code == keycodes['e']) and flags.ctrl then
if repeating ~= 0 then
scrolling = scrolling + 1
else
scrolling = 1
end
local scroll_mul = 1 + math.log(scrolling)
if code == keycodes['y'] then
scroll_y_delta = math.ceil(-1 * scroll_mul)
else
scroll_y_delta = math.floor(1 * scroll_mul)
end
log.d("Scrolling", scrolling, '-', scroll_y_delta)
elseif code == keycodes['h'] then
x_delta = step * mul * -1
elseif code == keycodes['l'] then
x_delta = step * mul
elseif code == keycodes['j'] then
y_delta = step * mul
elseif code == keycodes['k'] then
y_delta = step * mul * -1
end
if scroll_y_delta ~= 0 then
hs.eventtap.event.newScrollEvent({0, scroll_y_delta}, flags, 'line'):post()
end
if x_delta or y_delta then
coords.x = coords.x + x_delta
coords.y = coords.y + y_delta
if dragging then
postEvent(eventTypes.leftMouseDragged, coords, flags, 0)
else
hs.mouse.setAbsolutePosition(coords)
end
end
end
return true
end)
hs.hotkey.bind(tmod, tkey, nil, function(event)
local screen = hs.mouse.getCurrentScreen()
local frame = screen:fullFrame()
-- overlay = hs.drawing.rectangle(frame)
-- overlay:setFillColor({['red']=0, ['blue']=0, ['green']=0, ['alpha']=0.2})
-- overlay:setFill(true)
-- overlay:setLevel(hs.drawing.windowLevels['assistiveTechHigh'])
-- overlay:show()
hs.alert('Vi Mouse On')
orig_coords = hs.mouse.getAbsolutePosition()
tap:start()
end)
end
Loading…
Cancel
Save