Risposte:
Smart Scroll fa quello che stai cercando, con la sua funzione 'Grab Scroll'. Assegnalo a "Button 3 (Middle)" e il trascinamento su entrambi gli assi funzionerà in app come browser (Chrome), Terminal, Adobe Photoshop e Finder - nessuna app che ho provato non ha funzionato con esso (usando 4.0 beta su e su). Ha una prova gratuita.
L'ho fatto con Hammerspoon con il seguente script di configurazione ispirato a questo thread: https://github.com/tekezo/Karabiner/issues/814#issuecomment-337643019
passi:
Open Config
Incolla il seguente lua
script nella configurazione:
-- 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 lo fa, tra le altre cose. (Sono lo sviluppatore)
Ciò che lo differenzia dagli altri suggerimenti è la possibilità di usarlo in ogni app mac mentre identifica i collegamenti, ad esempio. (nel caso in cui usi il pulsante centrale trascina per afferrare e lanciare, ma desideri comunque che un clic sul pulsante centrale funga da pulsante centrale)
Con Smooze è più come afferrare-trascinare-lanciare che afferrare-trascinare. Il rilascio influenza lo slancio e l'animazione dello scroll, in modo simile allo scroll dell'iPhone.
C'è un'app open source molto carina chiamata Karabiner che farà questo e molto altro (rimappatura di tastiera e mouse ecc.). Vedi questa domanda per alcuni esempi. Inoltre per alcuni produttori forniscono software di controllo personalizzato che può consentire funzionalità migliorate / modificate (ad es. Logitech Control Center).
Come menzionato nei commenti seguenti, mentre una nuova versione di "Karabiner Elements" è stata rilasciata per MacOS Sierra (10.12) in poi, prevede solo il rimappatura basata su tastiera finora, quindi al momento non è possibile eseguire la rimappatura del mouse.
Tuttavia Hammerspoon è un altro strumento open source gratuito che può essere utilizzato, tra le altre cose, per rimappare i tasti del mouse (e / o della tastiera) a diverse funzioni. Dovrai installare lo strumento e fornirgli alcune configurazioni appropriate - vedi esempi qui per la rimappatura del mouse.
Per verificare quali tipi di eventi e mouseEventButtonNumbers vengono generati dal tuo dispositivo, puoi eseguirlo (copia / incolla le 4 linee nella console) nella console di Hammerspoon (usa reload config
per fermarlo):
hs.eventtap.new({"all"},function(e)
print(e,"mouseEventButtonNumber:",
e:getProperty(hs.eventtap.event.properties['mouseEventButtonNumber']))
end):start()
Nota: se hai installato gli strumenti Logitech Control Center (LCC), acquisisce gli eventi direttamente dai dispositivi Logitech utilizzando il modulo kernel installato in modo che Hammerspoon non possa vederli. Dovrai disinstallare LCC se vuoi rimappare i pulsanti del mouse usando Hammerspoon.
Dipende dal software, ad esempio Firefox lo supporta, mentre Google Chrome no.
Attualmente non esiste alcun software che abiliti tale funzionalità a livello di sistema in OS X, purtroppo.
Ho usato Better Touch Tool per assegnare Ctrl + tasto centrale a PgUp e Opzione + tasto centrale a PgDown. È gratuito, software eccellente e funziona bene.
+1 per Hammerspoon e uno script, un normale mouse / trackball mi fa impazzire su un Mac.
Ne ho scritto uno per scorrere mentre il pulsante centrale del mouse è premuto: più si sposta il mouse più velocemente scorrerà.
Il clic funziona ancora come un normale clic con una zona morta di 5 pixel, quindi non è necessario mantenere il mouse perfettamente fermo tra la pressione e il rilascio della rotellina.
------------------------------------------------------------------------------------------
-- 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
dovrebbe essere deltaY = deltaY * -1
e ho commentato deltaX = deltaX * -1
perché non volevo invertire l'asse X.