pynput
pynput copied to clipboard
mouse listener on_scroll not accurately capturing scroll dx dy values
Description
pynput's mouse Listener for on_scroll does not accurately capture the dx and dy values. When previously captured values are replayed through mouse.Controller, the resulting scroll falls short of expectations by a big margin.
Platform and pynput version MacOS 15.3 Sequoia pynput=1.8.1 Bluetooth Mouse with scroll wheel
To Reproduce
record_scroll.py
from pynput import mouse, keyboard
import json, time
events = []
startTime = time.time()
def write_events_local():
print("Writing events")
print(json.dumps(events))
with open(f"scroll_events.json", "w") as f:
json.dump(events, f)
def writeEventsAndClose():
# Stop listeners
mouse_listener.stop()
keyboard_listener.stop()
write_events_local()
def getTimeDiff():
global startTime
timeDiff = time.time() - startTime
startTime = time.time()
return timeDiff
def on_scroll(x, y, dx, dy):
print("on scroll")
print(f"x: {x}, y: {y}, dx: {dx}, dy: {dy}")
events.append({"type": "scroll", "x": x, "y": y, "dx": dx, "dy": dy, "time": getTimeDiff()})
def on_release(key):
global multi_keys
multi_keys = ""
if key == keyboard.Key.esc:
writeEventsAndClose()
return False
mouse_listener = mouse.Listener(on_move=None, on_scroll=on_scroll)
keyboard_listener = keyboard.Listener(on_release=on_release)
mouse_listener.start()
keyboard_listener.start()
mouse_listener.join()
keyboard_listener.join()
replay_scroll.py
import json, time
from pynput.mouse import Controller as MouseController
mouse = MouseController()
events = []
def get_events_local(filepath):
global events
events = []
with open(filepath, 'r') as file:
obj = json.load(file)
events = obj
get_events_local('scroll_events.json')
for event in events:
time.sleep(event['time'])
print(f"{(event['x'], event['y'])} scroll by {(event['dx'], event['dy'])}")
mouse.position = (event['x'], event['y'])
# time.sleep(0.1)
mouse.scroll(event['dx'], event['dy'])
time.sleep(3)
When the replay_scroll.py is run with the captured events array for scrolling, it is observed that the actual scroll distance on an application does not match up with the one while recording. Tried with various applications like Google Chrome, Sublime, Visual Studio code etc. - result is the same, i.e. falls short of original scroll expectation.
Also tried changing the Mouse "Scroll Speed" in MacOS settings. It does not help.
Got the same issue, please fix ❤️❤️❤️
Thank you for your report.
Unfortunately I do not have access to a macOS system, so I cannot really test any code for that platform. However, the handling in the controller and the one in the listener are suspiciously different.
Is it possible for you to test different values, @simplicity360 or @dat-lequoc? I believe one possible fix would be to store this event in a variable, and then call Quartz.CGEventSetIntegerValueField with values analogous to those in the listener.