How to simulate a mouse drag operation?
JazysYu opened this issue · comments
I want to press a keyboard key, which is equivalent to pressing the left mouse button.
But when I trigger hs.eventtap...leftMouseDown on the desktop and then move the mouse, it doesn't show the drag box like a real mouse left button down, or can drag to move the window below the mouse position, I tried leftMouseDown, mouseMoved, leftMouseDragged none of these combinations work. I noticed if the focusedWindow is not Finder's desktop, like "VSCode", it can have drag effect.
Is this action possible? Thanks.
Mouse drags are annoying... they require multiple events and "time" between each event to allow the receiving app to accept them... e.g.
local event = require("hs.eventtap").event
local screen = require("hs.screen")
local mouse = require("hs.mouse")
local application = require("hs.application")
finderSelectAll = function()
-- do your prep stuff here
local finder = application("Finder")
finder:activate()
local curPos = mouse.absolutePosition()
-- determine start, end, and delta of drag
local frame = screen.mainScreen():frame()
local fullFrame = screen.mainScreen():fullFrame()
local startPoint = {
x = frame.x,
y = frame.y
}
-- main screen may not be only one and may not start at 0, 0 so we use fullFrame
local endPoint = {
x = fullFrame.x + fullFrame.w,
y = fullFrame.y + fullFrame.h
}
local xDelta = endPoint.x - startPoint.x
local yDelta = endPoint.y - startPoint.y
-- perform drag in a coroutine so each step has a chance to be processed
local cr -- predeclare because we reference it from within the coroutine
-- to prevent premature garbage collection
cr = coroutine.wrap(function()
-- mouseDown
coroutine.applicationYield()
event.newMouseEvent(event.types.leftMouseDown, startPoint):post()
-- startDrag
coroutine.applicationYield()
event.newMouseEvent(event.types.leftMouseDragged, startPoint):post()
-- endDrag
coroutine.applicationYield()
event.newMouseEvent(event.types.leftMouseDragged, endPoint)
:setProperty(event.properties.mouseEventDeltaX, xDelta)
:setProperty(event.properties.mouseEventDeltaY, yDelta)
:post()
-- mouseUp
coroutine.applicationYield()
event.newMouseEvent(event.types.leftMouseUp, endPoint):post()
cr = nil -- clear coroutine since we're done
-- now do what follows the drag
mouse.absolutePosition(curPos)
end)
cr() -- start coroutine
end
Now, in the HS console, and in a relatively clear screen (I've found this doesn't work if there is another applications window near the starting or ending point), type finderSelectAll()
and it should select everything on your desktop.
Hope this gets you started in the right direction!
It worked. I tried leftMouseDown and then leftMouseDragged to endPoint with a delay of one second, it seems that one leftMouseDragged with startPoint is missing :)
Anyway this is a great code example, thanks a lot for your help!