ฉันสามารถเปิดใช้งานการเลื่อนด้วยการลากปุ่มกลางใน OS X ได้หรือไม่


16

ฉันมีเมาส์ที่มีสามปุ่ม แต่ไม่มีล้อ

ใน OS X มีวิธีใดบ้าง (อาจเป็นกับซอฟต์แวร์ addon) ที่ให้ฉันใช้ปุ่มที่สามในการเลื่อนโดยการกดค้างไว้และเลื่อนเมาส์?

คำตอบ:


10

Smart Scrollทำสิ่งที่คุณต้องการด้วยคุณสมบัติ 'Grab Scroll' กำหนดให้ 'ปุ่ม 3 (กลาง)' และการลากบนทั้งสองแกนจะทำงานในแอปเช่นเบราว์เซอร์ (Chrome), เทอร์มินัล, Adobe Photoshop และ Finder - ไม่มีแอพที่ฉันพยายามแล้วไม่ทำงาน (ใช้ 4.0 betas ขึ้น ๆ ) มีการทดลองใช้ฟรี

ป้อนคำอธิบายรูปภาพที่นี่


3

ฉันทำกับHammerspoonด้วยสคริปต์การกำหนดค่าต่อไปนี้ซึ่งได้รับแรงบันดาลใจจากกระทู้นี้: 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()
    

แค่ลองใช้และใช้งานได้อย่างสวยงาม
im_chc

เนื่องจากฉันต้องการให้ Y-scroll หมุนไปรอบ ๆ ฉันเปลี่ยนรหัส lua นิดหน่อย: เปลี่ยน "dy" ในบรรทัด "local scroll = hs.eventtap.event.newScrollEvent ({- dx * scrollmult, dy * scrollmult}, {}, 'pixel') "เป็นค่าลบ (ดังนั้นจะเป็น" -dy * scrollmult ")
im_chc

2

Smoozeทำเช่นนั้นเหนือสิ่งอื่นใด (ฉันเป็นผู้พัฒนา)

สิ่งที่แตกต่างจากคำแนะนำอื่น ๆ คือความสามารถในการใช้งานได้ในทุกแอป mac ในขณะที่ยังระบุลิงก์อยู่ (ในกรณีที่คุณใช้การลากปุ่มกลางเพื่อคว้าและโยน แต่ยังต้องการให้การคลิกปุ่มกลางทำหน้าที่เป็นปุ่มกลาง)

ด้วย Smooze เป็นเหมือนการลากแบบลากมากกว่าการลากแบบลาก การเปิดตัวมีผลต่อโมเมนตัมและภาพเคลื่อนไหวของการเลื่อนคล้ายกับการเลื่อนของ iPhone

ป้อนคำอธิบายรูปภาพที่นี่


2

มีแอพโอเพนซอร์ซที่ดีมาก ๆชื่อKarabinerซึ่งจะทำสิ่งนี้และอีกมากมาย (แป้นพิมพ์และเมาส์ remapping ฯลฯ ) ดูคำถามนี้สำหรับตัวอย่าง นอกจากนี้สำหรับผู้ผลิตบางรายพวกเขายังจัดหาซอฟต์แวร์ควบคุมแบบกำหนดเองซึ่งอาจอนุญาตให้มีการปรับปรุง / แก้ไขฟังก์ชั่น (เช่น Logitech Control Center)

ดังที่ได้กล่าวไว้ในความคิดเห็นด้านล่างว่าในขณะที่ 'Karabiner Elements' เวอร์ชันใหม่ได้รับการเผยแพร่สำหรับ MacOS Sierra (10.12) เป็นต้นไปจะให้เฉพาะการแมปผ่านแป้นพิมพ์เท่านั้นดังนั้นในปัจจุบันการแมปเมาส์จึงไม่สามารถทำได้

อย่างไรก็ตามแฮมเมอร์สปูนเป็นเครื่องมือโอเพนซอร์ซฟรีอีกหนึ่งตัวที่อาจใช้ในการทำการแมปปุ่มบนเมาส์ (และ / หรือแป้นพิมพ์) กับฟังก์ชั่นต่างๆ คุณจะต้องติดตั้งเครื่องมือและจัดหาด้วยการกำหนดค่าที่เหมาะสม - ดูตัวอย่างที่นี่เพื่อทำการแมปเมาส์ใหม่

ในการตรวจสอบว่าอุปกรณ์ของคุณสร้างเหตุการณ์ประเภทใดและ mouseEventButtonNumbers คุณสามารถเรียกใช้งานได้ (เพียงแค่คัดลอก / วาง 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


1
น่าเสียดายที่ Karabiner ไม่ทำงานกับ OSX ที่ทันสมัยอีกต่อไป ตอนนี้มี 'องค์ประกอบของคาราบิเนอร์' แต่มันมีฟังก์ชั่นการใช้งานครึ่งหนึ่งของต้นฉบับและนี่คือหนึ่งในสิ่งที่ไม่สามารถทำได้
นาธานฮอร์น

1
ใช่ปัจจุบันมี จำกัด ดังนั้นฉันจึงอัปเดตคำตอบเพื่อเพิ่มโซลูชันอื่น
Pierz

แฮมเมอร์สปูนเป็นทางออกที่ฉันทำไว้เมื่อวานนี้ข้อเสนอแนะที่ดีมาก! :) ด้วยเหตุผลบางอย่างฉันไม่สามารถผูกมันไว้กับปุ่มเมาส์ปุ่มใดปุ่มหนึ่งได้ แต่การจับคู่กับ ctrl + cmd นั้นทำงานได้ดี
นาธานฮอร์น

1
ฉันได้เพิ่มการแก้ไขอื่นเนื่องจากฉันมีปัญหานี้เมื่อฉันติดตั้ง LCC แล้ว แต่การถอนการติดตั้งจะแก้ไขได้ (เมื่อฉันทำงานซึ่งปุ่มใดสร้าง mouseEventButtonNumber - บน Marble Mouse ซ้ายมินิ - ปุ่มคือ 3 และอันที่เหมาะสมคือ 4) .
Pierz

ฉันสงสัยว่าอาจเป็นปัญหา! ขอบคุณสำหรับการยืนยันฉันจะแยกออกเมื่อฉันได้รับโอกาส
นาธานฮอร์นบี้

1

ขึ้นอยู่กับซอฟต์แวร์ - ตัวอย่างเช่น Firefox รองรับในขณะที่ Google Chrome ไม่รองรับ

ปัจจุบันยังไม่มีซอฟต์แวร์สำหรับเปิดใช้งานฟีเจอร์ดังกล่าวทั้งระบบใน OS X เศร้า


อาจจะไม่เข้ากันได้กับ Chrome ในปี 2011 แต่แน่นอนว่าในปี 2014 หลังจากไม่ต้องสงสัยเลยว่ามีการแก้ไขเล็กน้อย 'Grab Scroll' ของ Smart Scroll ทำงานได้อย่างราบรื่นกับ Chrome และ Opera ฉันสามารถยืนยันได้ ฉันคิดว่ามันกว้างทั้งระบบปฏิบัติการด้วยเช่นกันใน Finder, Adobe Photoshop และแม้แต่ Terminal ดังนั้นฉันคิดว่าข้อมูลของคุณล้าสมัย! :)


1

+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ควรเป็นdeltaY = deltaY * -1และฉันแสดงความคิดเห็นdeltaX = deltaX * -1เพราะฉันไม่ต้องการให้แกน X กลับด้าน
Tyler

ขอบคุณสำหรับการตรวจจับคำผิด ฉันเขียนมันใหม่และเปลี่ยนตัวเลือกเพื่อย้อนกลับการเลื่อนแนวตั้งเท่านั้น
TIM
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.