Вопрос или проблема
У меня есть мышь с тремя кнопками, но без колеса.
В OS X есть ли способ (возможно, с помощью дополнительного программного обеспечения), который позволил бы мне использовать третью кнопку для прокрутки, удерживая её и двигая мышь?
Я сделал это с помощью Hammerspoon с помощью следующего скрипта конфигурации, вдохновленного этой темой: https://github.com/tekezo/Karabiner/issues/814#issuecomment-337643019
Шаги:
- Установите Hammerspoon
- Нажмите на его значок меню и выберите
Open Config
-
Вставьте следующий
lua
скрипт в конфигурацию:-- УПРАВЛЕНИЕ ПРОКРУТКОЙ С УДЕРЖИВАНИЕМ КНОПКИ МЫШИ 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 -- отрицательный множитель заставляет мышь работать как традиционное колесо прокрутки 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') -- возвращаем мышь на место hs.mouse.setAbsolutePosition(oldmousepos) return true, {scroll} else return false, {} end end) overrideOtherMouseDown:start() overrideOtherMouseUp:start() dragOtherToScroll:start()
Smart Scroll делает то, что вам нужно, с помощью функции ‘Grab Scroll’. Назначьте её на ‘Button 3 (Middle)’, и перетаскивание по обеим осям будет работать в таких приложениях, как браузеры (Chrome), Terminal, Adobe Photoshop и Finder – ни одно приложение, с которым я пробовал, не работало с этим (используя бета-версии 4.0 и выше). У него есть бесплатная пробная версия.
Smooze делает это, среди прочего. (Я разработчик)
С Smooze это больше похоже на захват-перетаскивание-бросок, чем на захват-перетаскивание. Освобождение влияет на движение и анимацию прокрутки, похоже на прокрутку iPhone.
Обновлено (2022): Появилось новое программное обеспечение с открытым исходным кодом под названием Karabiner Elements, которое сделает это и много другого – оно может переназначить клавиатуру и переназначение мыши и т.д.
Это заменяет старое приложение ‘Karabiner’ (Смотрите этот вопрос для [старых] некоторых примеров) и теперь действительно предоставляет возможность переназначить как мышь, так и клавиатуру, как упомянул @Nathan в комментариях.
Другой вариант – Hammerspoon, который также является инструментом с открытым исходным кодом, который может быть использован, среди прочего, для переназначения клавиш на мыши (и/или клавиатуре) на разные функции. Вам нужно установить инструмент и предоставить ему соответствующую конфигурацию – смотрите примеры здесь для переназначения мыши.
Чтобы проверить, какие типы событий и 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 Centre (LCC) – они захватывают события напрямую из устройств Logitech с использованием их установленного модульного ядра, так что Hammerspoon не может их видеть. Вам нужно удалить LCC, если вы хотите переназначить кнопки мыши с помощью Hammerspoon.
+1 за Hammerspoon и скрипт, обычная мышь/трекбол сводит меня с ума на Mac.
Я написал один скрипт, чтобы прокручивать, пока нажата средняя кнопка мыши – чем дальше вы двигаете мышь, тем быстрее она прокручивается.
Щелчок по-прежнему работает как обычный щелчок с мертвой зоной 5 пикселей, так что вам не нужно держать мышь абсолютно неподвижной между нажатиями и отпусканием колеса.
------------------------------------------------------------------------------------------
-- АВТОПРОКРУТКА С КНОПКИ КОЛЕСА МЫШИ
-- timginter @ GitHub
------------------------------------------------------------------------------------------
-- идентификатор кнопки колеса мыши
local mouseScrollButtonId = 2
-- конфигурация скорости и направления прокрутки
local scrollSpeedMultiplier = 0.1
local scrollSpeedSquareAcceleration = true
local reverseVerticalScrollDirection = false
local mouseScrollTimerDelay = 0.01
-- конфигурация круга
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)
-- раскомментируйте строку ниже, чтобы увидеть идентификатор нажатой кнопки
--print(e:getProperty(hs.eventtap.event.properties['mouseEventButtonNumber']))
if e:getProperty(hs.eventtap.event.properties['mouseEventButtonNumber']) == mouseScrollButtonId then
-- удалите круг, если он существует
if mouseScrollCircle then
mouseScrollCircle:delete()
mouseScrollCircle = nil
end
-- остановите таймер, если он работает
if mouseScrollTimer then
mouseScrollTimer:stop()
mouseScrollTimer = nil
end
-- сохраните координаты мыши
mouseScrollStartPos = hs.mouse.absolutePosition()
mouseScrollDragPosX = mouseScrollStartPos.x
mouseScrollDragPosY = mouseScrollStartPos.y
-- начните таймер прокрутки
mouseScrollTimer = hs.timer.doAfter(mouseScrollTimerDelay, mouseScrollTimerFunction)
-- не отправляйте событие нажатия кнопки прокрутки
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
-- отправьте оригинальное событие отпускания кнопки, если оно было отпущено в пределах 'mouseScrollCircleDeadZone' пикселей от оригинальной позиции и цикл прокрутки не существует
mouseScrollPos = hs.mouse.absolutePosition()
xDiff = math.abs(mouseScrollPos.x - mouseScrollStartPos.x)
yDiff = math.abs(mouseScrollPos.y - mouseScrollStartPos.y)
if (xDiff < mouseScrollCircleDeadZone and yDiff < mouseScrollCircleDeadZone) and not mouseScrollCircle then
-- отключите переопределение мыши прокрутки
overrideScrollMouseDown:stop()
overrideScrollMouseUp:stop()
-- отправьте щелчок мыши прокрутки
hs.eventtap.otherClick(e:location(), mouseScrollButtonId)
-- повторно включите переопределение мыши прокрутки
overrideScrollMouseDown:start()
overrideScrollMouseUp:start()
end
-- удалите круг, если он существует
if mouseScrollCircle then
mouseScrollCircle:delete()
mouseScrollCircle = nil
end
-- остановите таймер, если он работает
if mouseScrollTimer then
mouseScrollTimer:stop()
mouseScrollTimer = nil
end
-- не отправляйте событие отпускания кнопки прокрутки
return true
end
end)
overrideScrollMouseDrag = hs.eventtap.new({ hs.eventtap.event.types.otherMouseDragged }, function(e)
-- проверка разумности
if mouseScrollDragPosX == nil or mouseScrollDragPosY == nil then
return true
end
-- обновите координаты мыши
mouseScrollDragPosX = mouseScrollDragPosX + e:getProperty(hs.eventtap.event.properties['mouseEventDeltaX'])
mouseScrollDragPosY = mouseScrollDragPosY + e:getProperty(hs.eventtap.event.properties['mouseEventDeltaY'])
-- не отправляйте событие перетаскивания кнопки прокрутки
return true
end)
function mouseScrollTimerFunction()
-- проверка разумности
if mouseScrollDragPosX ~= nil and mouseScrollDragPosY ~= nil then
-- получите разность координат курсора относительно оригинального нажатия
xDiff = math.abs(mouseScrollDragPosX - mouseScrollStartPos.x)
yDiff = math.abs(mouseScrollDragPosY - mouseScrollStartPos.y)
-- нарисуйте круг, если он еще не нарисован и курсор переместился более чем на 'mouseScrollCircleDeadZone' пикселей
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
-- отправьте событие прокрутки, если курсор переместился более чем на радиус круга
if xDiff > mouseScrollCircleRad or yDiff > mouseScrollCircleRad then
-- получите реальное значение xDiff и yDiff
deltaX = mouseScrollDragPosX - mouseScrollStartPos.x
deltaY = mouseScrollDragPosY - mouseScrollStartPos.y
-- используйте 'scrollSpeedMultiplier'
deltaX = deltaX * scrollSpeedMultiplier
deltaY = deltaY * scrollSpeedMultiplier
-- квадрат для лучшего ускорения прокрутки
if scrollSpeedSquareAcceleration then
-- модификация, чтобы сохранить отрицательные значения
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.ceil / math.floor - событие прокрутки принимает только целые числа
deltaXRounding = math.ceil
deltaYRounding = math.ceil
if deltaX < 0 then
deltaXRounding = math.floor
end
if deltaY < 0 then
deltaYRounding = math.floor
end
deltaX = deltaXRounding(deltaX)
deltaY = deltaYRounding(deltaY)
-- измените направление Y прокрутки, если 'reverseVerticalScrollDirection' установлено в true
if reverseVerticalScrollDirection then
deltaY = deltaY * -1
end
-- отправьте событие прокрутки
hs.eventtap.event.newScrollEvent({-deltaX, deltaY}, {}, 'pixel'):post()
end
end
-- перезапустите таймер
mouseScrollTimer = hs.timer.doAfter(mouseScrollTimerDelay, mouseScrollTimerFunction)
end
-- запустите функции переопределения
overrideScrollMouseDown:start()
overrideScrollMouseUp:start()
overrideScrollMouseDrag:start()
------------------------------------------------------------------------------------------
-- КОНЕЦ АВТОПРОКРУТКИ С КНОПКИ КОЛЕСА МЫШИ
------------------------------------------------------------------------------------------
Это зависит от программного обеспечения - например, Firefox поддерживает это, а Google Chrome - нет.
В настоящее время нет программного обеспечения, чтобы включить такую функцию на уровне системы в OS X, к сожалению.
Я использовал Better Touch Tool, чтобы назначить Ctrl+средний щелчок на PgUp, а Option+средний щелчок на PgDown. Это бесплатное, отличное программное обеспечение, которое работает хорошо.
Karabiner-Elements имеет это реализованным.
Установите его, затем перейдите на эту страницу пользовательских модификаций и импортируйте правило "Изменить движение мыши на прокрутку".
Я написал небольшую программу для этой цели: https://github.com/emreyolcu/drag-scroll. Это более легкое решение по сравнению с Hammerspoon.
Она либо переключает прокрутку, когда нажата кнопка мыши 5, либо временно активирует прокрутку, пока удерживается клавиша Shift. Вы можете настроить кнопку мыши и модификаторы, которые она использует.
Ответ или решение
Вопрос о том, возможно ли активировать прокрутку с помощью средней кнопки мыши в операционной системе macOS, актуален для многих пользователей, которые используют мыши без колеса прокрутки. Ниже приведены детальные рекомендации и возможные решения, которые помогут вам реализовать эту функциональность.
1. Использование Hammerspoon
Hammerspoon — это мощный инструмент для автоматизации, который позволяет вам настраивать работу клавиатуры и мыши в macOS. Для реализации функции прокрутки с помощью средней кнопки мыши можно воспользоваться следующим Lua-скриптом:
Шаги по установке:
- Скачать и установить Hammerspoon с официального сайта: Hammerspoon.
- Открыть конфигурационный файл Hammerspoon через меню в строке задач.
- Скопировать и вставить приведённый ниже скрипт в конфигурационный файл:
-- Установка кнопки для прокрутки
local scrollMouseButton = 2
local deferred = false
overrideOtherMouseDown = hs.eventtap.new({ hs.eventtap.event.types.otherMouseDown }, function(e)
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)
local pressedMouseButton = e:getProperty(hs.eventtap.event.properties['mouseEventButtonNumber'])
if scrollMouseButton == pressedMouseButton then
if (deferred) then
-- дополнительные действия для прокрутки
return true
end
return false
end
return false
end)
local oldmousepos = {}
local scrollmult = -4
dragOtherToScroll = hs.eventtap.new({ hs.eventtap.event.types.otherMouseDragged }, function(e)
local pressedMouseButton = e:getProperty(hs.eventtap.event.properties['mouseEventButtonNumber'])
if scrollMouseButton == pressedMouseButton then
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')
hs.mouse.setAbsolutePosition(oldmousepos)
return true, {scroll}
else
return false, {}
end
end)
overrideOtherMouseDown:start()
overrideOtherMouseUp:start()
dragOtherToScroll:start()
Этот скрипт позволит вам использовать среднюю кнопку для прокрутки при её удерживании и движении мыши.
2. Использование Smart Scroll
Smart Scroll — это приложение, предоставляющее функциональность «Grab Scroll». Оно позволяет назначить использование третьей кнопки мыши для прокрутки, и оно работает во множестве приложений, таких как браузеры (например, Google Chrome), терминал и другие. Вы можете скачать пробную версию: Smart Scroll.
3. Smooze
Smooze — ещё одно решение, которое предоставляет гибкие опции прокрутки с помощью средней кнопки мыши. Оно отличается от других решений тем, что сохраняет возможность взаимодействия со ссылками и позволяет настраивать поведение прокрутки. Программа имеет множество полезных функций, начиная от простого захвата прокрутки и заканчивая анимацией прокрутки, напоминающей поведение на iPhone Smooze.
4. Karabiner-Elements
Karabiner-Elements — это приложение для переприсвоения клавиш и кнопок мыши. Оно позволяет настраивать многие параметры, включая прокрутку на основе движения мыши. Для установки и настройки вам нужно:
- Скачать Karabiner-Elements: Karabiner-Elements.
- Перейти на страницу правил Custom Complex Modifications и импортировать правило «Change mouse motion to scroll».
Заключение
Каждое из предложенных решений имеет свои преимущества и недостатки, поэтому выбор зависит от ваших личных предпочтений и задач. Установка одного из этих приложений позволит вам включить прокрутку путем перетаскивания с помощью средней кнопки мыши в macOS. Настройка может занять некоторое время, но в итоге обеспечит значительно более удобный интерфейс работы с вашим компьютером.
Если у вас остались вопросы или требуется дополнительная помощь, обратитесь к сообществу пользователей или специализированным форумам, где вы сможете получить более детальные советы.