Відповіді:
Смарт-прокрутка робить те, що ви шукаєте, завдяки своїй функції «Захопити прокрутку». Призначте його "Кнопка 3 (середня)", і перетягування по обох осях працюватиме в таких додатках, як браузери (Chrome), термінал, Adobe Photoshop та Finder - жоден додаток, який я намагався, не працював з ним (використовуючи 4.0 бета-версії та вгору). У ньому є безкоштовна пробна версія.
Я зробив це з Hammerspoon із наступним сценарієм конфігурації, натхненним цією ниткою: https://github.com/tekezo/Karabiner/isissue/814#issuecomment-337643019
Кроки:
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()
Smooze робить це, серед іншого. (Я розробник)
Що відрізняє його від інших пропозицій, це можливість використовувати його у кожному додатку для Mac, хоча, як і раніше, ідентифікувати посилання. (якщо ви використовуєте середню кнопку перетягування, щоб захопити та кинути, але все ж хочете, щоб натискання середньої кнопки діяло як середня кнопка)
З Smooze більше схоже на grab-drag-кидання, ніж grab-drag. Випуск впливає на імпульс та анімацію прокрутки, подібно до прокрутки iPhone.
Існує дуже хороший додаток з відкритим кодом під назвою Karabiner, який буде робити це і багато іншого (перескладання клавіатури та миші тощо). Дивіться це питання для деяких прикладів. Також для деяких виробників вони постачають програмне забезпечення для користування, яке може вдосконалювати / модифікувати функціональність (наприклад, Logitech Control Center).
Як зазначалося в коментарях нижче, поки нова версія «Karabiner Elements» була випущена для MacOS Sierra (10.12) і надалі вона передбачає лише перестановку на основі клавіатури - тому в даний час перезавантаження миші не може бути виконано з нею.
Однак Hammerspoon - це ще один безкоштовний інструмент з відкритим кодом, який, крім багатьох інших, може бути використаний для перестановки клавіш миші (та / або клавіатури) на різні функції. Вам необхідно встановити інструмент і поставити його з деякою відповідною конфігурацією - дивіться приклади тут для перепризначення миші.
Щоб перевірити, які типи подій та мишіEventButtonNumbers створюються вашим пристроєм, ви можете запустити це (просто скопіюйте / вставте 4 рядки в консоль) на консолі Hammerspoon (Використовуйте reload config
для зупинки):
hs.eventtap.new({"all"},function(e)
print(e,"mouseEventButtonNumber:",
e:getProperty(hs.eventtap.event.properties['mouseEventButtonNumber']))
end):start()
Примітка: Якщо ви встановили інструменти Logitech Control Center (LCC) - він захоплює події безпосередньо з пристроїв Logitech, використовуючи встановлений модуль ядра, щоб Hammerspoon не міг їх бачити. Вам потрібно буде видалити LCC, якщо ви хочете перевстановити кнопки миші за допомогою Hammerspoon.
Це залежить від програмного забезпечення - наприклад, Firefox підтримує його, а Google Chrome - ні.
На жаль, на жаль, не існує програмного забезпечення, яке б дало змогу ввімкнути таку функцію в OS X
Я використовував інструмент Better Touch, щоб призначити Ctrl + середній клік до PgUp, а Option + Середній клік - PgDown. Це безкоштовно, відмінне програмне забезпечення та працює добре.
+1 для Hammerspoon та сценарію, звичайна миша / трекбол змушує мене зле на 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.floor - scroll event accepts only integers
deltaX = math.floor(deltaX)
deltaY = math.floor(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
------------------------------------------------------------------------------------------
deltaX = deltaY * -1
повинна бути, deltaY = deltaY * -1
і я прокоментував це, deltaX = deltaX * -1
оскільки не хотів перевернутий вісь X.