2021-10-16 10:41:42 +00:00
|
|
|
local app = require('hs.application')
|
|
|
|
local eventtap = require('hs.eventtap')
|
|
|
|
local geometry = require('hs.geometry')
|
|
|
|
local hotkey = require('hs.hotkey')
|
|
|
|
local layout = require('hs.layout')
|
|
|
|
local win = require('hs.window')
|
2021-05-28 16:41:55 +00:00
|
|
|
|
2021-10-16 16:01:33 +00:00
|
|
|
-- Custom variables
|
|
|
|
--------------------
|
|
|
|
|
2017-06-12 10:06:46 +00:00
|
|
|
local hyper = { 'cmd', 'alt', 'shift', 'ctrl' }
|
2021-11-26 10:55:58 +00:00
|
|
|
local alt = { 'alt' }
|
|
|
|
local altShift = { 'alt', 'shift' }
|
2021-05-28 16:41:55 +00:00
|
|
|
local laptopMonitor = "Built-in Retina Display"
|
2021-06-16 13:51:24 +00:00
|
|
|
local mainMonitor = "DELL U3415W"
|
2023-04-08 20:45:12 +00:00
|
|
|
-- local mainMonitor = "DELL U3419W"
|
2017-06-12 10:06:46 +00:00
|
|
|
|
2021-10-16 16:01:33 +00:00
|
|
|
-- Custom positions and layouts where which apps can be on the screen
|
|
|
|
--------------------
|
|
|
|
|
2021-10-16 10:41:42 +00:00
|
|
|
local screenPositions = {
|
2022-09-30 08:16:31 +00:00
|
|
|
left = geometry.rect(0, 0, 0.5, 1),
|
|
|
|
leftTop = { x = 0, y = 0, w = 0.5, h = 0.5 },
|
|
|
|
leftBottom = { x= 0, y = 0.5, w = 0.5, h = 0.5 },
|
|
|
|
right = geometry.rect(0.5, 0, 0.5, 1),
|
|
|
|
rightTop = { x = 0.5, y = 0, w = 0.5, h = 0.5 },
|
|
|
|
rightBottom = { x= 0.5, y = 0.5, w = 0.5, h = 0.5 },
|
|
|
|
top = geometry.rect(0, 0, 1, 0.5),
|
|
|
|
bottom = geometry.rect(0, 0.5, 1, 0.5),
|
2022-10-17 09:05:30 +00:00
|
|
|
center = geometry.rect(0.2, 0.2, 0.6, 0.6),
|
|
|
|
max = geometry.rect(0.1, 0.1, 0.8, 0.8),
|
2021-10-16 10:41:42 +00:00
|
|
|
full = geometry.rect(0, 0, 1, 1),
|
2021-05-28 16:41:55 +00:00
|
|
|
}
|
2017-06-12 10:06:46 +00:00
|
|
|
|
2021-05-28 16:41:55 +00:00
|
|
|
local layoutDouble = {
|
2021-10-16 16:01:33 +00:00
|
|
|
{ "Calendar", nil, laptopMonitor, screenPositions.full, nil, nil },
|
2021-10-16 10:41:42 +00:00
|
|
|
{ "Firefox", nil, mainMonitor, screenPositions.left, nil, nil },
|
2021-10-16 16:01:33 +00:00
|
|
|
{ "ForkLift", nil, laptopMonitor, screenPositions.full, nil, nil },
|
2022-07-06 10:55:07 +00:00
|
|
|
{ "Mail", nil, laptopMonitor, screenPositions.full, nil, nil },
|
2024-06-12 19:48:09 +00:00
|
|
|
{ "Microsoft Teams", nil, mainMonitor, screenPositions.rightBottom, nil, nil },
|
2021-10-16 10:41:42 +00:00
|
|
|
{ "Signal", nil, mainMonitor, screenPositions.rightBottom, nil, nil },
|
2022-08-18 10:55:22 +00:00
|
|
|
{ "Strongbox", nil, laptopMonitor, screenPositions.full, nil, nil },
|
2024-04-10 12:40:26 +00:00
|
|
|
{ "TIDAL", nil, laptopMonitor, screenPositions.full, nil, nil },
|
2023-09-28 10:45:45 +00:00
|
|
|
{ "WezTerm", nil, mainMonitor, screenPositions.right, nil, nil },
|
2021-05-28 16:41:55 +00:00
|
|
|
}
|
2017-06-17 11:31:25 +00:00
|
|
|
|
2021-05-28 16:41:55 +00:00
|
|
|
local layoutSingle = {
|
2021-10-16 16:01:33 +00:00
|
|
|
{ "Calendar", nil, laptopMonitor, screenPositions.full, nil, nil },
|
|
|
|
{ "Firefox", nil, laptopMonitor, screenPositions.full, nil, nil },
|
|
|
|
{ "ForkLift", nil, laptopMonitor, screenPositions.full, nil, nil },
|
2022-07-06 10:55:07 +00:00
|
|
|
{ "Mail", nil, laptopMonitor, screenPositions.full, nil, nil },
|
2024-07-24 11:36:04 +00:00
|
|
|
{ "Microsoft Teams", nil, laptopMonitor, screenPositions.full, nil, nil },
|
2021-10-16 16:01:33 +00:00
|
|
|
{ "Signal", nil, laptopMonitor, screenPositions.full, nil, nil },
|
2022-08-18 10:55:22 +00:00
|
|
|
{ "Strongbox", nil, laptopMonitor, screenPositions.full, nil, nil },
|
2024-04-10 12:40:26 +00:00
|
|
|
{ "TIDAL", nil, laptopMonitor, screenPositions.full, nil, nil },
|
2023-09-28 10:45:45 +00:00
|
|
|
{ "WezTerm", nil, laptopMonitor, screenPositions.full, nil, nil },
|
2021-05-28 16:41:55 +00:00
|
|
|
}
|
2017-06-12 18:39:54 +00:00
|
|
|
|
2024-01-19 10:47:50 +00:00
|
|
|
local appsToLaunch = {
|
2021-05-28 16:41:55 +00:00
|
|
|
"Calendar",
|
|
|
|
"Firefox",
|
|
|
|
"ForkLift",
|
2022-07-06 10:55:07 +00:00
|
|
|
"Mail",
|
2024-06-12 19:48:09 +00:00
|
|
|
"Microsoft Teams",
|
2021-05-28 16:41:55 +00:00
|
|
|
"Signal",
|
2022-08-18 10:55:22 +00:00
|
|
|
"Strongbox",
|
2024-04-10 12:40:26 +00:00
|
|
|
"TIDAL",
|
2023-09-28 10:45:45 +00:00
|
|
|
"WezTerm",
|
2021-05-28 16:41:55 +00:00
|
|
|
}
|
2017-06-12 18:39:54 +00:00
|
|
|
|
2021-10-16 16:01:33 +00:00
|
|
|
-- Local helper functions
|
|
|
|
--------------------
|
|
|
|
|
2023-08-08 16:06:56 +00:00
|
|
|
local function tablelength(T)
|
|
|
|
local count = 0
|
|
|
|
for _ in pairs(T) do count = count + 1 end
|
|
|
|
return count
|
|
|
|
end
|
|
|
|
|
2021-05-28 16:41:55 +00:00
|
|
|
local function launchApps()
|
2024-01-19 10:47:50 +00:00
|
|
|
for i, appName in ipairs(appsToLaunch) do
|
2021-05-28 16:41:55 +00:00
|
|
|
app.launchOrFocus(appName)
|
|
|
|
end
|
2017-06-12 18:39:54 +00:00
|
|
|
end
|
|
|
|
|
2021-05-28 16:41:55 +00:00
|
|
|
local function moveMouse()
|
2024-06-12 19:48:09 +00:00
|
|
|
local pt = geometry.rectMidPoint(win.focusedWindow():frame())
|
2021-05-28 16:41:55 +00:00
|
|
|
hs.mouse.absolutePosition(pt)
|
2017-08-24 14:38:29 +00:00
|
|
|
end
|
|
|
|
|
2021-10-16 10:41:42 +00:00
|
|
|
local function applyPosition(pos)
|
2021-06-15 11:21:42 +00:00
|
|
|
local w = win.focusedWindow()
|
2021-10-16 10:41:42 +00:00
|
|
|
local screenName = w:screen():name()
|
|
|
|
local tempPos = screenPositions[pos]
|
2023-08-08 16:06:56 +00:00
|
|
|
local tempLayout = { { app.frontmostApplication(), w, screenName, tempPos, nil, nil } }
|
2021-10-16 10:41:42 +00:00
|
|
|
layout.apply(tempLayout)
|
2021-06-17 07:03:08 +00:00
|
|
|
end
|
|
|
|
|
2024-06-12 19:48:09 +00:00
|
|
|
-- Key-trap (cat/baby-mode)
|
|
|
|
--------------------
|
|
|
|
local function babymode()
|
2024-07-24 11:36:04 +00:00
|
|
|
local alert = require('hs.alert')
|
2024-06-12 19:48:09 +00:00
|
|
|
alert('Babymode activated')
|
|
|
|
|
|
|
|
Mousetrap = eventtap.new({
|
|
|
|
eventtap.event.types.leftMouseDown,
|
|
|
|
eventtap.event.types.rightMouseDown,
|
|
|
|
}, function(event)
|
|
|
|
return true -- Stop event from propogating
|
|
|
|
end)
|
|
|
|
|
|
|
|
Keytrap = eventtap.new({ eventtap.event.types.keyDown }, function(event)
|
|
|
|
local keyCode = event:getKeyCode()
|
|
|
|
|
|
|
|
if (math.fmod(keyCode, 2) == 0) then
|
|
|
|
hs.window.switcher.nextWindow()
|
|
|
|
end
|
|
|
|
|
|
|
|
if keyCode == hs.keycodes.map['\\'] then
|
|
|
|
local mod = event:getFlags()
|
|
|
|
if (mod.ctrl == true and mod.shift == true and mod.alt == true and mod.cmd == true) then
|
|
|
|
alert('Babymode deactivated')
|
|
|
|
Mousetrap:stop()
|
|
|
|
Keytrap:stop()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return true -- Stop event from propogating
|
|
|
|
end)
|
|
|
|
|
|
|
|
Mousetrap:start()
|
|
|
|
Keytrap:start()
|
|
|
|
end
|
|
|
|
|
|
|
|
hotkey.bind(hyper, '\\', function() babymode() end)
|
|
|
|
|
2022-09-30 08:16:31 +00:00
|
|
|
-- Window management and general config
|
|
|
|
--------------------
|
|
|
|
|
|
|
|
win.animationDuration = 0
|
2023-08-08 16:06:56 +00:00
|
|
|
app.enableSpotlightForNameSearches(true)
|
2022-09-30 08:16:31 +00:00
|
|
|
|
2021-10-16 16:01:33 +00:00
|
|
|
-- Keybindings
|
|
|
|
--------------------
|
2021-10-16 10:41:42 +00:00
|
|
|
|
|
|
|
-- Applying main two layouts
|
|
|
|
hotkey.bind(hyper, 'q', function() layout.apply(layoutSingle) end)
|
2023-08-08 16:06:56 +00:00
|
|
|
hotkey.bind(hyper, 'w', function()
|
2024-07-24 11:36:04 +00:00
|
|
|
local screen = require('hs.screen')
|
|
|
|
|
|
|
|
if (tablelength(screen.allScreens()) == 2) then
|
2023-08-08 16:06:56 +00:00
|
|
|
layout.apply(layoutDouble)
|
|
|
|
else
|
|
|
|
layout.apply(layoutSingle)
|
|
|
|
end
|
|
|
|
end)
|
2021-01-27 16:08:05 +00:00
|
|
|
|
2021-10-16 16:01:33 +00:00
|
|
|
-- Direct app navigation
|
2023-09-28 10:45:45 +00:00
|
|
|
hotkey.bind(hyper, 'a', function() app.launchOrFocus('WezTerm') end)
|
2021-05-28 16:41:55 +00:00
|
|
|
hotkey.bind(hyper, 's', function() app.launchOrFocus('Firefox') end)
|
2022-03-02 11:11:51 +00:00
|
|
|
hotkey.bind(hyper, 'd', function() app.launchOrFocus('ForkLift') end)
|
2021-05-28 16:41:55 +00:00
|
|
|
hotkey.bind(hyper, 'g', function() launchApps() end)
|
|
|
|
|
2021-10-16 16:01:33 +00:00
|
|
|
-- Moving windows around / navigating windows
|
2021-05-28 16:41:55 +00:00
|
|
|
hotkey.bind(hyper, '[', function() win.focusedWindow():moveOneScreenNorth(); moveMouse() end)
|
|
|
|
hotkey.bind(hyper, ']', function() win.focusedWindow():moveOneScreenSouth(); moveMouse() end)
|
2021-10-16 10:41:42 +00:00
|
|
|
hotkey.bind(hyper, 'z', function() applyPosition('full'); moveMouse() end)
|
|
|
|
hotkey.bind(hyper, 'x', function() applyPosition('max'); moveMouse() end)
|
|
|
|
hotkey.bind(hyper, 'c', function() applyPosition('center'); moveMouse() end)
|
|
|
|
hotkey.bind(hyper, 'h', function() applyPosition('left'); moveMouse() end)
|
|
|
|
hotkey.bind(hyper, 'u', function() applyPosition('leftTop'); moveMouse() end)
|
|
|
|
hotkey.bind(hyper, 'n', function() applyPosition('leftBottom'); moveMouse() end)
|
|
|
|
hotkey.bind(hyper, 'l', function() applyPosition('right'); moveMouse() end)
|
|
|
|
hotkey.bind(hyper, 'i', function() applyPosition('rightTop'); moveMouse() end)
|
|
|
|
hotkey.bind(hyper, 'm', function() applyPosition('rightBottom'); moveMouse() end)
|
|
|
|
hotkey.bind(hyper, 'k', function() applyPosition('top'); moveMouse() end)
|
|
|
|
hotkey.bind(hyper, 'j', function() applyPosition('bottom'); moveMouse() end)
|
2017-06-12 18:39:54 +00:00
|
|
|
|
2017-06-17 11:52:33 +00:00
|
|
|
-- map hyper + number to the corresponding fn-key, since the touchbar
|
|
|
|
-- kinda sucks, and karabiner-elements is breaking fn-function to show keys
|
2021-05-28 16:41:55 +00:00
|
|
|
hotkey.bind(hyper, '1', function() eventtap.keyStroke({}, 'F1') end)
|
|
|
|
hotkey.bind(hyper, '2', function() eventtap.keyStroke({}, 'F2') end)
|
|
|
|
hotkey.bind(hyper, '3', function() eventtap.keyStroke({}, 'F3') end)
|
|
|
|
hotkey.bind(hyper, '4', function() eventtap.keyStroke({}, 'F4') end)
|
|
|
|
hotkey.bind(hyper, '5', function() eventtap.keyStroke({}, 'F5') end)
|
|
|
|
hotkey.bind(hyper, '6', function() eventtap.keyStroke({}, 'F6') end)
|
|
|
|
hotkey.bind(hyper, '7', function() eventtap.keyStroke({}, 'F7') end)
|
|
|
|
hotkey.bind(hyper, '8', function() eventtap.keyStroke({}, 'F8') end)
|
|
|
|
hotkey.bind(hyper, '9', function() eventtap.keyStroke({}, 'F9') end)
|
|
|
|
hotkey.bind(hyper, '0', function() eventtap.keyStroke({}, 'F10') end)
|
|
|
|
hotkey.bind(hyper, '-', function() eventtap.keyStroke({}, 'F11') end)
|
|
|
|
hotkey.bind(hyper, '=', function() eventtap.keyStroke({}, 'F12') end)
|
2017-06-17 11:52:33 +00:00
|
|
|
|
2021-11-26 10:55:58 +00:00
|
|
|
-- macos keyboard input source switching is still broken AF, so we map
|
|
|
|
-- umlauts and others manually with hammerspoon, instead of using US-german-layout
|
|
|
|
-- dunno why I had to add a space beföre ´äÄ, but this way it works
|
|
|
|
hotkey.bind(alt, 'a', function() eventtap.keyStrokes(' ä') end)
|
|
|
|
hotkey.bind(alt, 'o', function() eventtap.keyStrokes('ö') end)
|
|
|
|
hotkey.bind(alt, 's', function() eventtap.keyStrokes('ß') end)
|
|
|
|
hotkey.bind(alt, 'u', function() eventtap.keyStrokes('ü') end)
|
|
|
|
hotkey.bind(altShift, 'a', function() eventtap.keyStrokes(' Ä') end)
|
|
|
|
hotkey.bind(altShift, 'o', function() eventtap.keyStrokes('Ö') end)
|
|
|
|
hotkey.bind(altShift, 'u', function() eventtap.keyStrokes('Ü') end)
|