イベント発火のみで、入力の検出はできていません
結論
from pynput.mouse import Button
from pynput.mouse._darwin import _button_value
from enum import Enum
class Buttons(Enum):
left = Button.left.value
right = Button.right.value
middle = Button.middle.value
x1 = _button_value("kCGEventOther", 3) # ここ重要
x2 = _button_value("kCGEventOther", 4) # ここ重要
使い方
from pynput.mouse import Controller
controller = Controller()
controller.click(Buttons.x1) # 第4ボタン
controller.click(Buttons.x2) # 第5ボタン
システム設定からアクセシビリティにアプリを追加するのを忘れないようにしましょう。
はじめに
pynputを使ってマウスのサイドボタンを入力させる場合、Windowsでは以下のように書くことができます。
from pynput.mouse import Button, Controller
controller = Controller()
controller.click(Button.x1) # 第4ボタン
controller.click(Button.x2) # 第5ボタン
しかしMacではAttributeErrorとなってしまいます。
AttributeError: type object 'Button' has no attribute 'x1'
これは、pynputがMacのサイドボタンに対応していないためです。
辿り着いた経緯
pynputの内部コードを覗いてみます。
...
def _button_value(base_name, mouse_button):
...
return (
tuple(
getattr(Quartz, '%sMouse%s' % (base_name, name))
for name in ('Down', 'Up', 'Dragged')),
mouse_button)
class Button(enum.Enum):
"""The various buttons.
"""
unknown = None
left = _button_value('kCGEventLeft', 0)
middle = _button_value('kCGEventOther', 2)
right = _button_value('kCGEventRight', 1)
...
kCGEvent
というキーワードが出てきたので調べてみると、Apple Developerのサイトがヒットしました。
case otherMouseDown
Specifies a mouse down event with one of buttons 2-31.
case otherMouseUp
Specifies a mouse up event with one of buttons 2-31.
case otherMouseDragged
Specifies a mouse drag event with one of buttons 2-31 down.
どうやらボタン2〜31は全てkCGEventOther
として括られるようです。
ボタン0が左クリック、ボタン1が右クリックで、ボタン2がミドルクリック(マウスホイール)だとすると、サイドボタンは3と4である可能性が高そうです。
2〜31のkCGEventOther
を実行して検証してみます。
from pynput.mouse import Controller, Button
from pynput.mouse._darwin import _button_value
from time import sleep
from enum import Enum
addition = {}
for i in range(2, 32):
button = _button_value("kCGEventOther", i)
addition[f"button{i}"] = button
# Enumの拡張については下を参考
# https://zenn.dev/yuji38kwmt/articles/63cda54021ecf3
tmp = {e.name: e.value for e in Button} | addition
buttons = Enum("buttons", tmp)
sleep(5) # この間にブラウザなど、サイドボタンの動きがわかるアプリにフォーカスする
controller = Controller()
for i in range(2, 32):
controller.click(buttons[f"button{i}"])
print(f"Clicked button {i}")
sleep(3)
検証の結果、button3の時に「戻る」、button4の時に「進む」が実行されました。
終わりに
Windows / Mac両対応のコード
from pynput.mouse import Button as bt
from enum import Enum
import platform
system = platform.system()
class Button(Enum):
if system == "Windows":
left = bt.left.value
right = bt.right.value
middle = bt.middle.value
x1 = bt.x1.value
x2 = bt.x2.value
elif system == "Darwin":
from pynput.mouse._darwin import _button_value
left = bt.left.value
right = bt.right.value
middle = bt.middle.value
x1 = _button_value("kCGEventOther", 3)
x2 = _button_value("kCGEventOther", 4)
elif system == "Linux":
pass # 検証環境をサッと用意できなかったので割愛
または
from pynput.mouse import Button
import sys
if sys.platform == "darwin":
from pynput.mouse._darwin import _button_value
from enum import Enum
Button = Enum("Button", {e.name: e.value for e in Button} | {"x1": _button_value("kCGEventOther", 3), "x2": _button_value("kCGEventOther", 4)})
検証
from pynput.mouse import Controller
from time import sleep
controller = Controller()
sleep(5)
controller.click(Button.x1, 1)
sleep(3)
controller.click(Button.x2, 1)