![我可以在 OS X 中启用鼠标中键拖动滚动吗?](https://linux22.com/image/1281151/%E6%88%91%E5%8F%AF%E4%BB%A5%E5%9C%A8%20OS%20X%20%E4%B8%AD%E5%90%AF%E7%94%A8%E9%BC%A0%E6%A0%87%E4%B8%AD%E9%94%AE%E6%8B%96%E5%8A%A8%E6%BB%9A%E5%8A%A8%E5%90%97%EF%BC%9F.png)
我有一个有三个按钮但没有滚轮的鼠标。
在 OS X 中,有没有什么方法(也许使用插件软件)可以让我通过按住第三个按钮并移动鼠标来使用它进行滚动?
答案1
我做了锤子勺使用受此线程启发的以下配置脚本:https://github.com/tekezo/Karabiner/issues/814#issuecomment-337643019
脚步:
- 安装 Hammerspoon
- 点击其菜单图标并选择
Open Config
将以下
lua
脚本粘贴到配置中:-- HANDLE SCROLLING WITH MOUSE BUTTON PRESSED local scrollMouseButton = 2 local deferred = false overrideOtherMouseDown = hs.eventtap.new({ hs.eventtap.event.types.otherMouseDown }, function(e) -- print("down") local pressedMouseButton = e:getProperty(hs.eventtap.event.properties['mouseEventButtonNumber']) if scrollMouseButton == pressedMouseButton then deferred = true return true end end) overrideOtherMouseUp = hs.eventtap.new({ hs.eventtap.event.types.otherMouseUp }, function(e) -- print("up") local pressedMouseButton = e:getProperty(hs.eventtap.event.properties['mouseEventButtonNumber']) if scrollMouseButton == pressedMouseButton then if (deferred) then overrideOtherMouseDown:stop() overrideOtherMouseUp:stop() hs.eventtap.otherClick(e:location(), pressedMouseButton) overrideOtherMouseDown:start() overrideOtherMouseUp:start() return true end return false end return false end) local oldmousepos = {} local scrollmult = -4 -- negative multiplier makes mouse work like traditional scrollwheel dragOtherToScroll = hs.eventtap.new({ hs.eventtap.event.types.otherMouseDragged }, function(e) local pressedMouseButton = e:getProperty(hs.eventtap.event.properties['mouseEventButtonNumber']) -- print ("pressed mouse " .. pressedMouseButton) if scrollMouseButton == pressedMouseButton then -- print("scroll"); deferred = false oldmousepos = hs.mouse.getAbsolutePosition() local dx = e:getProperty(hs.eventtap.event.properties['mouseEventDeltaX']) local dy = e:getProperty(hs.eventtap.event.properties['mouseEventDeltaY']) local scroll = hs.eventtap.event.newScrollEvent({-dx * scrollmult, dy * scrollmult},{},'pixel') -- put the mouse back hs.mouse.setAbsolutePosition(oldmousepos) return true, {scroll} else return false, {} end end) overrideOtherMouseDown:start() overrideOtherMouseUp:start() dragOtherToScroll:start()
答案2
智能滚动它的“抓取滚动”功能可以满足您的需求。将其分配给“按钮 3(中间)”,在浏览器(Chrome)、终端、Adobe Photoshop 和 Finder 等应用中,拖动两个轴即可 - 我尝试过的所有应用都无法使用它(使用 4.0 及以上版本的测试版)。它有免费试用版。
答案3
轻抚除其他外,它还能做这些事情。(我是开发人员)
它与其他建议的不同之处在于,它能够在每个 Mac 应用程序中使用它,同时仍能识别链接。(以防您使用中键拖动来抓取和抛出,但仍然希望中键单击充当中键)
使用 Smooze 更像是抓取-拖拽-抛出,而不是抓取-拖拽。释放会影响滚动的动量和动画,类似于 iPhone 滚动。
答案4
+1 表示锤子勺和一个脚本,一个普通的鼠标/轨迹球让我在 Mac 上抓狂。
我编写了一个在按下鼠标中键时滚动的程序 - 鼠标移动得越远,滚动的速度就越快。
点击仍然像正常点击一样工作,具有 5 像素的死区,因此您不必在按下和释放滚轮之间保持鼠标完全静止。
------------------------------------------------------------------------------------------
-- AUTOSCROLL WITH MOUSE WHEEL BUTTON
-- timginter @ GitHub
------------------------------------------------------------------------------------------
-- id of mouse wheel button
local mouseScrollButtonId = 2
-- scroll speed and direction config
local scrollSpeedMultiplier = 0.1
local scrollSpeedSquareAcceleration = true
local reverseVerticalScrollDirection = false
local mouseScrollTimerDelay = 0.01
-- circle config
local mouseScrollCircleRad = 10
local mouseScrollCircleDeadZone = 5
------------------------------------------------------------------------------------------
local mouseScrollCircle = nil
local mouseScrollTimer = nil
local mouseScrollStartPos = 0
local mouseScrollDragPosX = nil
local mouseScrollDragPosY = nil
overrideScrollMouseDown = hs.eventtap.new({ hs.eventtap.event.types.otherMouseDown }, function(e)
-- uncomment line below to see the ID of pressed button
--print(e:getProperty(hs.eventtap.event.properties['mouseEventButtonNumber']))
if e:getProperty(hs.eventtap.event.properties['mouseEventButtonNumber']) == mouseScrollButtonId then
-- remove circle if exists
if mouseScrollCircle then
mouseScrollCircle:delete()
mouseScrollCircle = nil
end
-- stop timer if running
if mouseScrollTimer then
mouseScrollTimer:stop()
mouseScrollTimer = nil
end
-- save mouse coordinates
mouseScrollStartPos = hs.mouse.getAbsolutePosition()
mouseScrollDragPosX = mouseScrollStartPos.x
mouseScrollDragPosY = mouseScrollStartPos.y
-- start scroll timer
mouseScrollTimer = hs.timer.doAfter(mouseScrollTimerDelay, mouseScrollTimerFunction)
-- don't send scroll button down event
return true
end
end)
overrideScrollMouseUp = hs.eventtap.new({ hs.eventtap.event.types.otherMouseUp }, function(e)
if e:getProperty(hs.eventtap.event.properties['mouseEventButtonNumber']) == mouseScrollButtonId then
-- send original button up event if released within 'mouseScrollCircleDeadZone' pixels of original position and scroll circle doesn't exist
mouseScrollPos = hs.mouse.getAbsolutePosition()
xDiff = math.abs(mouseScrollPos.x - mouseScrollStartPos.x)
yDiff = math.abs(mouseScrollPos.y - mouseScrollStartPos.y)
if (xDiff < mouseScrollCircleDeadZone and yDiff < mouseScrollCircleDeadZone) and not mouseScrollCircle then
-- disable scroll mouse override
overrideScrollMouseDown:stop()
overrideScrollMouseUp:stop()
-- send scroll mouse click
hs.eventtap.otherClick(e:location(), mouseScrollButtonId)
-- re-enable scroll mouse override
overrideScrollMouseDown:start()
overrideScrollMouseUp:start()
end
-- remove circle if exists
if mouseScrollCircle then
mouseScrollCircle:delete()
mouseScrollCircle = nil
end
-- stop timer if running
if mouseScrollTimer then
mouseScrollTimer:stop()
mouseScrollTimer = nil
end
-- don't send scroll button up event
return true
end
end)
overrideScrollMouseDrag = hs.eventtap.new({ hs.eventtap.event.types.otherMouseDragged }, function(e)
-- sanity check
if mouseScrollDragPosX == nil or mouseScrollDragPosY == nil then
return true
end
-- update mouse coordinates
mouseScrollDragPosX = mouseScrollDragPosX + e:getProperty(hs.eventtap.event.properties['mouseEventDeltaX'])
mouseScrollDragPosY = mouseScrollDragPosY + e:getProperty(hs.eventtap.event.properties['mouseEventDeltaY'])
-- don't send scroll button drag event
return true
end)
function mouseScrollTimerFunction()
-- sanity check
if mouseScrollDragPosX ~= nil and mouseScrollDragPosY ~= nil then
-- get cursor position difference from original click
xDiff = math.abs(mouseScrollDragPosX - mouseScrollStartPos.x)
yDiff = math.abs(mouseScrollDragPosY - mouseScrollStartPos.y)
-- draw circle if not yet drawn and cursor moved more than 'mouseScrollCircleDeadZone' pixels
if mouseScrollCircle == nil and (xDiff > mouseScrollCircleDeadZone or yDiff > mouseScrollCircleDeadZone) then
mouseScrollCircle = hs.drawing.circle(hs.geometry.rect(mouseScrollStartPos.x - mouseScrollCircleRad, mouseScrollStartPos.y - mouseScrollCircleRad, mouseScrollCircleRad * 2, mouseScrollCircleRad * 2))
mouseScrollCircle:setStrokeColor({["red"]=0.3, ["green"]=0.3, ["blue"]=0.3, ["alpha"]=1})
mouseScrollCircle:setFill(false)
mouseScrollCircle:setStrokeWidth(1)
mouseScrollCircle:show()
end
-- send scroll event if cursor moved more than circle's radius
if xDiff > mouseScrollCircleRad or yDiff > mouseScrollCircleRad then
-- get real xDiff and yDiff
deltaX = mouseScrollDragPosX - mouseScrollStartPos.x
deltaY = mouseScrollDragPosY - mouseScrollStartPos.y
-- use 'scrollSpeedMultiplier'
deltaX = deltaX * scrollSpeedMultiplier
deltaY = deltaY * scrollSpeedMultiplier
-- square for better scroll acceleration
if scrollSpeedSquareAcceleration then
-- mod to keep negative values
deltaXDirMod = 1
deltaYDirMod = 1
if deltaX < 0 then
deltaXDirMod = -1
end
if deltaY < 0 then
deltaYDirMod = -1
end
deltaX = deltaX * deltaX * deltaXDirMod
deltaY = deltaY * deltaY * deltaYDirMod
end
-- math.ceil / math.floor - scroll event accepts only integers
deltaXRounding = math.ceil
deltaYRounding = math.ceil
if deltaX < 0 then
deltaXRounding = math.floor
end
if deltaY < 0 then
deltaYRounding = math.floor
end
deltaX = deltaXRounding(deltaX)
deltaY = deltaYRounding(deltaY)
-- reverse Y scroll if 'reverseVerticalScrollDirection' set to true
if reverseVerticalScrollDirection then
deltaY = deltaY * -1
end
-- send scroll event
hs.eventtap.event.newScrollEvent({-deltaX, deltaY}, {}, 'pixel'):post()
end
end
-- restart timer
mouseScrollTimer = hs.timer.doAfter(mouseScrollTimerDelay, mouseScrollTimerFunction)
end
-- start override functions
overrideScrollMouseDown:start()
overrideScrollMouseUp:start()
overrideScrollMouseDrag:start()
------------------------------------------------------------------------------------------
-- END OF AUTOSCROLL WITH MOUSE WHEEL BUTTON
------------------------------------------------------------------------------------------