¿Puedo habilitar el desplazamiento con el botón central arrastrado en OS X?


16

Tengo un mouse con tres botones pero sin rueda.

En OS X, ¿hay alguna forma (tal vez con un software adicional) que me permita usar mi tercer botón para desplazarme al sostenerlo y mover el mouse?

Respuestas:


10

Smart Scroll hace lo que estás buscando, con su función 'Grab Scroll'. Asignarlo al 'Botón 3 (Medio)' y arrastrar en ambos ejes funcionará en aplicaciones como navegadores (Chrome), Terminal, Adobe Photoshop y Finder; ninguna aplicación que he probado no ha funcionado con él (usando el 4.0 betas arriba y arriba). Tiene una prueba gratuita.

ingrese la descripción de la imagen aquí


3

Lo hice con Hammerspoon con el siguiente script de configuración inspirado en este hilo: https://github.com/tekezo/Karabiner/issues/814#issuecomment-337643019

Pasos:

  • Instalar Hammerspoon
  • Haga clic en su icono de menú y seleccione Open Config
  • Pegue el siguiente luascript en la configuración:

    -- 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()
    

solo lo probé y funciona de maravilla.
im_chc

Como prefiero hacer que el desplazamiento Y sea al revés, he cambiado un poco el código lua: cambie "dy" en la línea "desplazamiento local = hs.eventtap.event.newScrollEvent ({- dx * scrollmult, dy * scrollmult}, {}, 'pixel') "a negativo (por lo que sería" -dy * scrollmult ")
im_chc

2

Smooze hace eso, entre otras cosas. (Soy el desarrollador)

Lo que lo diferencia de otras sugerencias es la capacidad de usarlo en todas las aplicaciones de Mac sin dejar de identificar enlaces, por ejemplo. (en caso de que use el botón central, arrastre para agarrar y lanzar, pero aún así desea que un clic en el botón central actúe como botón central)

Con Smooze es más como agarrar y arrastrar que agarrar y arrastrar. El lanzamiento afecta el impulso y la animación del desplazamiento, similar al desplazamiento del iPhone.

ingrese la descripción de la imagen aquí


2

Hay una muy buena aplicación de código abierto llamada Karabiner que hará esto y mucho más (reasignación de teclado y mouse, etc.). Vea esta pregunta para algunos ejemplos. También para ciertos fabricantes suministran software de control personalizado que puede permitir una funcionalidad mejorada / modificada (por ejemplo, Logitech Control Center).

Como se menciona en los comentarios a continuación, si bien hasta ahora se ha lanzado una nueva versión de 'Karabiner Elements' para MacOS Sierra (10.12), solo proporciona una reasignación basada en el teclado, por lo que actualmente no se puede reasignar el mouse.

Sin embargo, Hammerspoon es otra herramienta gratuita de código abierto que se puede usar, entre muchas otras cosas, para reasignar las teclas del mouse (y / o teclado) a diferentes funciones. Deberá instalar la herramienta y proporcionarle alguna configuración adecuada; consulte los ejemplos aquí para la reasignación del mouse.

Para verificar qué tipos de evento y mouseEventButtonNumbers está generando su dispositivo, puede ejecutar esto (simplemente copie / pegue las 4 líneas en la consola) en la consola Hammerspoon (Use reload configpara detenerlo):

hs.eventtap.new({"all"},function(e)
print(e,"mouseEventButtonNumber:",
e:getProperty(hs.eventtap.event.properties['mouseEventButtonNumber']))
end):start()

Nota: Si ha instalado las herramientas del Centro de control de Logitech (LCC), toma los eventos directamente de los dispositivos Logitech utilizando su módulo de kernel instalado para que Hammerspoon no pueda verlos. Deberá desinstalar LCC si desea reasignar los botones del mouse con Hammerspoon.


1
Lamentablemente, Karabiner ya no funciona con OSX moderno. Hay un 'Karabiner Elements' ahora que sí, pero tiene la mitad de la funcionalidad del original, y esta es una de las cosas que no puede hacer.
Nathan Hornby

1
Sí, actualmente está limitado, así que actualicé mi respuesta para agregar otra solución.
Pierz

Hammerspoon es la solución a la que llegué ayer, ¡tan buena sugerencia! :) Por alguna razón, no pude hacer que se uniera a uno de los botones del mouse, pero mapearlo a ctrl + cmd parecía funcionar bien.
Nathan Hornby el

1
Agregué otra edición, ya que tuve este problema cuando instalé LCC, pero la desinstalé lo arregló (una vez que trabajé qué botones generaron qué mouseEventButtonNumber - en mi minibotón izquierdo Marble Mouse es 3 y el derecho es 4) .
Pierz el

¡Sospeché que ese podría ser el problema! Gracias por la confirmación, lo solucionaré cuando tenga la oportunidad.
Nathan Hornby

1

Depende del software; por ejemplo, Firefox lo admite, mientras que Google Chrome no.

Actualmente, lamentablemente, no hay software para habilitar dicha función en todo el sistema en OS X.


Tal vez no era compatible con Chrome en 2011, pero ciertamente en 2014, después de algunas revisiones, sin duda, el 'Grab Scroll' de Smart Scroll funciona sin problemas con Chrome y Opera, puedo confirmarlo. Creo que también abarca todo el sistema operativo, ya que funciona en Finder, Adobe Photoshop e incluso Terminal. ¡Así que creo que sus datos están desactualizados! :)


1

+1 para Hammerspoon y un script, un mouse / trackball normal me vuelve loco en una Mac.

Escribí uno para desplazarme mientras se presiona el botón central del mouse: cuanto más mueva el mouse, más rápido se desplazará.

Click sigue funcionando como un clic normal con una zona muerta de 5 píxeles, por lo que no tiene que mantener el mouse completamente quieto entre presionar y soltar la rueda.

------------------------------------------------------------------------------------------
-- 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
------------------------------------------------------------------------------------------

Característica asesina! Muchas gracias, exactamente lo que estaba buscando. Sin embargo deltaX = deltaY * -1, un error debería ser deltaY = deltaY * -1y lo comenté deltaX = deltaX * -1porque no quería invertir el eje X.
Tyler

Gracias por detectar el error tipográfico. Lo reescribí un poco y cambié la opción de revertir el desplazamiento vertical solamente
TIM
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.