OS X에서 중간 버튼 드래그로 스크롤 할 수 있습니까?


16

버튼이 3 개인 마우스가 있지만 휠은 없습니다.

OS X에는 세 번째 버튼을 사용하여 스크롤하고 마우스를 움직여 스크롤 할 수있는 방법이 있습니까?

답변:


10

Smart Scroll 은 'Grab Scroll'기능을 사용하여 원하는 것을 수행합니다. '버튼 3 (중간)'에 할당하고 브라우저 (Chrome), 터미널, Adobe Photoshop 및 Finder와 같은 앱에서 두 축을 드래그하면 작동합니다-시도한 앱이 작동하지 않습니다 (4.0 사용) 베타). 무료 평가판이 있습니다.

여기에 이미지 설명을 입력하십시오


3

이 스레드에서 영감을 얻은 다음 구성 스크립트 로 Hammerspoon 으로 해냈습니다 : https://github.com/tekezo/Karabiner/issues/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()
    

그것을 시도하고 아름답게 작동합니다.
im_chc

Y- 스크롤을 다른 방향으로 돌리는 것을 선호하기 때문에 루아 코드를 약간 변경했습니다. "local scroll = hs.eventtap.event.newScrollEvent ({-dx * scrollmult, dy * scrollmult}, {}, 'pixel') "를 음수로 변경 ("-dy * scrollmult "가 됨)
im_chc

2

스무 즈 는 무엇보다도 그 일을합니다. (저는 개발자입니다)

다른 제안과 다른 점은 모든 Mac 앱에서 링크를 식별하면서 링크를 식별하는 기능입니다. (가운데 버튼을 사용하여 잡아서 던지지 만 가운데 버튼 클릭이 가운데 버튼으로 작용하기를 원하는 경우)

Smooze를 사용하면 드래그-드래그보다 드래그-드로우와 비슷합니다. 이 릴리스는 iPhone 스크롤과 유사하게 스크롤의 운동량과 애니메이션에 영향을줍니다.

여기에 이미지 설명을 입력하십시오


2

Karabiner 라는 멋진 오픈 소스 앱 이 있습니다.이 기능은 훨씬 더 많은 기능을 제공합니다 (키보드 및 마우스 리 맵핑 등). 몇 가지 예는 이 질문 을 참조하십시오 . 또한 특정 제조업체의 경우 개선 / 수정 기능 (예 : Logitech Control Center)을 허용 할 수있는 사용자 지정 제어 소프트웨어를 제공합니다.

아래 의견에서 언급했듯이 MacOS Sierra (10.12) 이후에는 새로운 버전의 'Karabiner Elements'가 출시되었지만 지금까지는 키보드 기반 리 맵핑 만 제공하므로 현재 마우스 리 맵핑을 수행 할 수 없습니다.

그러나 Hammerspoon 은 다른 무료 오픈 소스 도구로, 마우스 및 / 또는 키보드의 키를 다른 기능에 다시 매핑하는 데 사용할 수 있습니다. 도구를 설치하고 적절한 구성을 제공해야합니다 . 마우스 다시 매핑에 대한 예는 여기 를 참조하십시오 .

장치에서 어떤 이벤트 유형과 mouseEventButtonNumbers가 생성되는지 확인하려면 Hammerspoon 콘솔에서이를 실행하십시오 (4 줄을 콘솔에 복사 / 붙여 넣기 만하면 됨 reload config).

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

참고 : LCC (Logitech Control Center) 도구를 설치 한 경우 설치된 커널 모듈을 사용하여 Logitech 장치에서 직접 이벤트를 가져와 Hammerspoon에서이를 볼 수 없습니다. Hammerspoon을 사용하여 마우스 버튼을 다시 매핑하려면 LCC를 제거해야합니다.


1
불행히도 Karabiner는 더 이상 최신 OSX에서 작동하지 않습니다. 이제는 'Karabiner Elements'가 있지만 원래 기능의 절반이 있으며 이것이 할 수없는 것 중 하나입니다.
Nathan Hornby

1
예, 현재 제한되어 있으므로 다른 솔루션을 추가하기 위해 답변을 업데이트했습니다.
Pierz

Hammerspoon은 어제 착륙 한 솔루션이므로 좋은 제안입니다! :) 어떤 이유로 마우스 버튼 중 하나에 바인딩 할 수 없었지만 ctrl + cmd에 매핑하는 것이 정상적으로 작동하는 것 같습니다.
Nathan Hornby

1
LCC를 설치할 때이 문제가 있었으므로 다른 편집을 추가했습니다.하지만 LCC를 제거하면 수정되었습니다 (마우스 마우스 왼쪽 미니 버튼은 3이고 오른쪽 버튼은 4입니다. .
Pierz

나는 그것이 문제일지도 모른다고 생각했다! 확인 주셔서 감사합니다, 나는 기회를 얻을 때 그것을 분류합니다.
Nathan Hornby

1

소프트웨어에 따라 다릅니다 (예 : Firefox는 소프트웨어를 지원하지만 Chrome은 지원하지 않습니다).

현재 슬프게도 OS X에서 이러한 기능을 시스템 전체에서 활성화하는 소프트웨어는 없습니다.


어쩌면 2011 년 Chrome과 호환되지 않았지만 2014 년에는 확실히 몇 가지 수정 사항이 있었지만 Smart Scroll의 'Grab Scroll'은 Chrome 및 Opera와 원활하게 작동합니다. Finder, Adobe Photoshop 및 심지어 터미널에서도 작동하기 때문에 OS 전체라고 생각합니다. 데이터가 오래된 것 같습니다. :)

1

Better Touch Tool 을 사용 하여 Ctrl + 중간 클릭을 PgUp에, Option + 중간 클릭을 PgDown에 할당했습니다. 무료이며 우수한 소프트웨어이며 잘 작동합니다.


1

Hammerspoon과 스크립트의 경우 +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.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있어야하며 X 축이 반전되는 것을 원하지 않기 때문에 deltaY = deltaY * -1주석을 달았습니다 deltaX = deltaX * -1.
Tyler

오타를 찾아 주셔서 감사합니다. 나는 그것을 약간 다시 작성하고 세로 스크롤 만 역전하는 옵션을 변경했습니다
TIM
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.