-
-
Save blissdev/bba381996a5e797a4ad9029bba2a8448 to your computer and use it in GitHub Desktop.
Hammerspoon script for ensuring Sidecar is active when iPad is plugged in (macOS 10.15)
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
hs.loadSpoon('SpoonInstall') | |
spoon.SpoonInstall.use_syncinstall = true | |
Install = spoon.SpoonInstall | |
log = hs.logger.new('init', 5) | |
-- function debugUI(msg, table) | |
-- log:d(msg) | |
-- log:d(hs.inspect(table)) | |
-- end | |
function connectToSidecar(msg, results, count) | |
local item | |
sidecarItemFound = (count > 0) | |
if not sidecarItemFound then | |
return log:d("Can't get Sidecar connection menu item:", msg) | |
end | |
item = results[1] | |
if item.AXMenuItemMarkChar == nil then | |
-- log:d("Connecting to Sidecar...") | |
item:doAXPress() | |
else | |
-- log:d("Closing menu - already connected to Sidecar...") | |
item.AXParent:doAXCancel() | |
end | |
end | |
function stopConnectToSidecarItemSearchTimer() | |
if connectToSidecarItemSearchTimer then | |
connectToSidecarItemSearchTimer:stop() | |
connectToSidecarItemSearchTimer = nil | |
end | |
end | |
function displaysMenu(msg, results, count) | |
local menu, connectToSneezerItemSearch | |
if count == 0 then | |
return log:d("Can't get displays menu:", msg) | |
end | |
menu = results[1] | |
menu:doAXPress() | |
connectToSneezerItemSearch = hs.axuielement.searchCriteriaFunction({ | |
{attribute = 'AXRole', value = 'AXMenuItem'}, | |
{attribute = 'AXIdentifier', value = '_deviceSelected:'}, | |
{attribute = 'AXTitle', value = 'Sneezer'}}) | |
-- menu:elementSearch(debugUI, connectToSneezer, | |
-- {objectOnly = false, asTree = true, depth = 2}) | |
-- iPad may not appear immediately in the Displays menu | |
-- wait up to 3 seconds for it to appear | |
stopConnectToSidecarItemSearchTimer() | |
sidecarItemFound = false | |
connectToSidecarItemSearchTimer = hs.timer.doUntil( | |
function() | |
return sidecarItemFound | |
end, | |
function() | |
menu:elementSearch(connectToSidecar, connectToSneezerItemSearch, | |
{count = 1, depth = 2, noCallback = true}) | |
end, | |
0.5) | |
hs.timer.doAfter(3, stopConnectToSidecarItemSearchTimer) | |
end | |
function connectSidecar() | |
local suisApp, suisAX, displayMenuSearch | |
suisApp = hs.application.find('com.apple.systemuiserver') | |
suisAX = hs.axuielement.applicationElement(suisApp) | |
displayMenuSearch = hs.axuielement.searchCriteriaFunction({ | |
{attribute = 'AXRole', value = 'AXMenuBarItem'}, | |
{attribute = 'AXSubrole', value = 'AXMenuExtra'}, | |
{attribute = 'AXDescription', value = '^Displays', pattern = true} | |
}) | |
-- suisAX:elementSearch(debugUI, displayMenuSearch, | |
-- {objectOnly = false, asTree = true, depth = 2}) | |
suisAX:elementSearch(displaysMenu, displayMenuSearch, | |
{count = 1, depth = 2}) | |
end | |
-- what we actually get when the iPad connects: | |
-- connect, disconnect, connect | |
-- so, don't trigger twice within half a second | |
connectSidecarTimer = hs.timer.delayed.new(0.5, function() | |
connectSidecar() | |
end) | |
function iPadConnected(connected) | |
-- log:d("iPad connected?", connected) | |
if connected then | |
connectSidecarTimer:start() | |
else | |
connectSidecarTimer:stop() | |
end | |
end | |
Install:andUse( | |
"USBDeviceActions", | |
{ | |
config = { | |
devices = { | |
iPad = { fn = iPadConnected } | |
} | |
}, | |
start = true | |
} | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment