Hook and simulate global mouse events in pure Python

Related tags

Hardwaremouse
Overview

mouse

Take full control of your mouse with this small Python library. Hook global events, register hotkeys, simulate mouse movement and clicks, and much more.

Huge thanks to Kirill Pavlov for donating the package name. If you are looking for the Cheddargetter.com client implementation, pip install mouse==0.5.0.

Features

  • Global event hook on all mice devices (captures events regardless of focus).
  • Listen and sends mouse events.
  • Works with Windows and Linux (requires sudo).
  • Works with MacOS (requires granting accessibility permissions to terminal/python in System Preferences -> Security & Privacy)
  • Pure Python, no C modules to be compiled.
  • Zero dependencies on Windows and Linux. Trivial to install and deploy, just copy the files.
  • Python 2 and 3.
  • Includes high level API (e.g. record and play.
  • Events automatically captured in separate thread, doesn't block main program.
  • Tested and documented.

This program makes no attempt to hide itself, so don't use it for keyloggers.

Usage

Install the PyPI package:

$ sudo pip install mouse

or clone the repository (no installation required, source files are sufficient):

$ git clone https://github.com/boppreh/mouse

Then check the API docs to see what features are available.

Known limitations:

  • Events generated under Windows don't report device id (event.device == None). #21
  • To avoid depending on X the Linux parts reads raw device files (/dev/input/input*) but this requries root.
  • Other applications, such as some games, may register hooks that swallow all key events. In this case mouse will be unable to report events.

API

Table of Contents

class mouse.ButtonEvent

ButtonEvent(event_type, button, time)

ButtonEvent.button

Alias for field number 1

ButtonEvent.count(self, value, /)

Return number of occurrences of value.

ButtonEvent.event_type

Alias for field number 0

ButtonEvent.index(self, value, start=0, stop=9223372036854775807, /)

Return first index of value.

Raises ValueError if the value is not present.

ButtonEvent.time

Alias for field number 2

mouse.DOUBLE

= 'double'

mouse.DOWN

= 'down'

mouse.LEFT

= 'left'

mouse.MIDDLE

= 'middle'

class mouse.MoveEvent

MoveEvent(x, y, time)

MoveEvent.count(self, value, /)

Return number of occurrences of value.

MoveEvent.index(self, value, start=0, stop=9223372036854775807, /)

Return first index of value.

Raises ValueError if the value is not present.

MoveEvent.time

Alias for field number 2

MoveEvent.x

Alias for field number 0

MoveEvent.y

Alias for field number 1

mouse.RIGHT

= 'right'

mouse.UP

= 'up'

class mouse.WheelEvent

WheelEvent(delta, time)

WheelEvent.count(self, value, /)

Return number of occurrences of value.

WheelEvent.delta

Alias for field number 0

WheelEvent.index(self, value, start=0, stop=9223372036854775807, /)

Return first index of value.

Raises ValueError if the value is not present.

WheelEvent.time

Alias for field number 1

mouse.X

= 'x'

mouse.X2

= 'x2'

mouse.version

= '0.7.1'

mouse.is_pressed(button='left')

[source]

Returns True if the given button is currently pressed.

mouse.press(button='left')

[source]

Presses the given button (but doesn't release).

mouse.release(button='left')

[source]

Releases the given button.

mouse.click(button='left')

[source]

Sends a click with the given button.

mouse.double_click(button='left')

[source]

Sends a double click with the given button.

mouse.right_click()

[source]

Sends a right click with the given button.

mouse.wheel(delta=1)

[source]

Scrolls the wheel delta clicks. Sign indicates direction.

mouse.move(x, y, absolute=True, duration=0, steps_per_second=120.0)

[source]

Moves the mouse. If absolute, to position (x, y), otherwise move relative to the current position. If duration is non-zero, animates the movement. The fps of the animation is determined by 'steps_per_second', default is 120.

mouse.drag(start_x, start_y, end_x, end_y, absolute=True, duration=0)

[source]

Holds the left mouse button, moving from start to end position, then releases. absolute and duration are parameters regarding the mouse movement.

mouse.on_button(callback, args=(), buttons=('left', 'middle', 'right', 'x', 'x2'), types=('up', 'down', 'double'))

[source]

Invokes callback with args when the specified event happens.

mouse.on_click(callback, args=())

[source]

Invokes callback with args when the left button is clicked.

mouse.on_double_click(callback, args=())

[source]

Invokes callback with args when the left button is double clicked.

mouse.on_right_click(callback, args=())

[source]

Invokes callback with args when the right button is clicked.

mouse.on_middle_click(callback, args=())

[source]

Invokes callback with args when the middle button is clicked.

mouse.wait(button='left', target_types=('up', 'down', 'double'))

[source]

Blocks program execution until the given button performs an event.

mouse.get_position()

[source]

Returns the (x, y) mouse position.

mouse.hook(callback)

[source]

Installs a global listener on all available mouses, invoking callback each time it is moved, a key status changes or the wheel is spun. A mouse event is passed as argument, with type either mouse.ButtonEvent, mouse.WheelEvent or mouse.MoveEvent.

Returns the given callback for easier development.

mouse.unhook(callback)

[source]

Removes a previously installed hook.

mouse.unhook_all()

[source]

Removes all hooks registered by this application. Note this may include hooks installed by high level functions, such as record.

mouse.record(button='right', target_types=('down',))

[source]

Records all mouse events until the user presses the given button. Then returns the list of events recorded. Pairs well with play(events).

Note: this is a blocking function. Note: for more details on the mouse hook and events see hook.

mouse.play(events, speed_factor=1.0, include_clicks=True, include_moves=True, include_wheel=True)

[source]

Plays a sequence of recorded events, maintaining the relative time intervals. If speed_factor is <= 0 then the actions are replayed as fast as the OS allows. Pairs well with record().

The parameters include_* define if events of that type should be inluded in the replay or ignored.

Comments
  • Sending mouse events doesn't work.

    Sending mouse events doesn't work.

    Everything that simulate mouse event doesn't work, except on positioning/moving the cursor. Listening to mouse event works fine. My machine running on Debian 4.19.28-2 (2019-03-18) i686 GNU/Linux.

    opened by angeloped 6
  • Add MacOS (darwin) support

    Add MacOS (darwin) support

    • Re-used code from https://github.com/boppreh/keyboard (_darwinmouse.py) and adapted it to the event data structures used in this repo
    • Tested on macos 11 (Big Sur).
    • Solves #29 #30
    opened by dorinclisu 3
  • OSError: Unsupported platform 'Darwin'

    OSError: Unsupported platform 'Darwin'

    I'm getting the following error message:

    Traceback (most recent call last): File "count_keystrokes.py", line 1, in <module> import keyboard, mouse File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/mouse/__init__.py", line 51, in <module> raise OSError("Unsupported platform '{}'".format(_platform.system())) OSError: Unsupported platform 'Darwin'

    opened by kylefoley76 3
  • Capturing active window with mouse/keyboard events?

    Capturing active window with mouse/keyboard events?

    Are there plans to capture the active window that is beneath the mouse/keyboard events? This would help when one wants to ensure that the keyboard is replayed in the correct window.

    opened by reckoner 3
  • mouse.on_double_click not working

    mouse.on_double_click not working

    Hi,

    I have the issue where callback passed to mouse.on_double_click isn't invoked.

    I took a quick peek and it seems that handlermethod defined in mouse.on_button gets called twice successively. Each ButtonEvent passed to the handler has button = 'left' and event_type = 'down' members, instead of button = 'left' and event_type = 'double' which the handler checks for.

    This is the code I'm talking about.

    def on_button(callback, args=(), buttons=(LEFT, MIDDLE, RIGHT, X, X2), types=(UP, DOWN, DOUBLE)):
        """ Invokes `callback` with `args` when the specified event happens. """
        if not isinstance(buttons, (tuple, list)):
            buttons = (buttons,)
        if not isinstance(types, (tuple, list)):
            types = (types,)
    
        def handler(event):
            if isinstance(event, ButtonEvent):
                if event.event_type in types and event.button in buttons:
                    callback(*args)
        _listener.add_handler(handler)
        return handler
    

    I'm a little busy at the moment, but if I find time I'll make an attempt at fixing this.

    opened by dino8890 3
  • mouse.move doesnt accept a list

    mouse.move doesnt accept a list

    Doing this:

    button_left = [400, 960]
    button_middle = [480, 960]
    button_right = [580, 960]
    button_choices = [button_left, button_middle, button_right]
    mouse.move(random.choice(button_choices))
    
    TypeError: move() missing 1 required positional argument: 'y'
    

    Is there some other way i can do this?

    opened by Motzumoto 2
  • [help with code] high cpu usage

    [help with code] high cpu usage

    So, currently this is my code, i need to constantly check if the left mouse button is pressed, but, this code is taking about 25% of my CPU. How i can solve this problem?

    import mouse

    def main():

    while True:
        if mouse.is_pressed(button='left'):
            print('Left mouse is down!')
    

    if name == 'main': main()

    opened by skhrlx 2
  • mouse.move not moving to correct coordinates

    mouse.move not moving to correct coordinates

    When using mouse.move(), the coordinates are not correct, ie: if I have this:

    mouse.move(0, 1080, absolute=True)
    print(mouse.get_position())
    

    it should go to the bottom left (which it does) yet getting the mouse position reveals its actually 863. If I then do mouse.move(0, 863, absolute=True), it puts me at the bottom left again, further testing reveals it isn't going to the correct spot. This also happens on the x-axis, giving me a max of 1535.

    opened by Underslash12 2
  • Remove claim to support MacOS X from setup.py

    Remove claim to support MacOS X from setup.py

    It's kind of highly misleading to claim MacOS X support in setup.py while the code does in fact not support it. Other people might get confused as well. So removing this bit would be only fair: Operating System :: MacOS :: MacOS X

    See also #30.

    opened by deeplook 2
  • cannot figure out how to use mouse.on_double_click on Windows

    cannot figure out how to use mouse.on_double_click on Windows

    With the following code, I think the sayHello function should print out something when double clicking left mouse button , but none , so what's wrong here ?

    import mouse
    
    
    def sayHello():
        print(mouse.get_position(),'sayHello')
    mouse.on_double_click(sayHello)  # lambda: print(11111111111) callback, args=()
    
    mouse.wait(button='left', target_types=('double',))
    
    

    Tested on Win7 32 bit, Python 3.5.2

    opened by redstoneleo 2
  • PyPi MacOS Support

    PyPi MacOS Support

    I'm writing a small package that is dependent on mouse. However, for MacOS, I've found the only way to utilize mouse is to build using git+https://github.com/boppreh/mouse.git. Unfortunately, PyPi doesn't allow direct dependencies like this. Is there any plan to release a MacOS supported version to PyPi? If not, I'll refactor to not be dependent on mouse. Thanks for your work!

    opened by gansel51 1
  • get_position altered after importing pyautogui

    get_position altered after importing pyautogui

    Hi,

    After importing pyautogui, it appears that the screen size is altered and so for position given by get_position function.

    import mouse
    mouse.get_position()
    import pyautogui
    mouse.get_position()
    

    Here's what I get when I position my mouse in the bottom right corner, i get:

    >>> import mouse
    >>> mouse.get_position()
    (1279, 719)
    >>> import pyautogui
    >>> mouse.get_position()
    (1919, 1079)
    

    Is this normal behaviour ? Any workaround ?

    Versions: mouse 0.7.1 PyAutoGUI 0.9.53 Python 3.8.5 Windows 11

    opened by asasa137 0
  • Touchscreen support - Question

    Touchscreen support - Question

    so i was wondering if we have touchscreen support via mouse.

    my testing program:

    import mouse
    import time
    
    events = []
    mouse.hook(events.append)
    while 1:
        mouse._listener.queue.join()
        for event in events:
            print(event)
        del events[:]
        time.sleep(0.25)
    

    and if i touch and release the touchscreen i get:

    ButtonEvent(event_type='down', button='?', time=1664808330.854423)
    ButtonEvent(event_type='up', button='?', time=1664808331.035416)
    

    now i tried to trigger a callback-function via mouse.on_button But it looks like this doesnt work - since button "?" is not implemented?

    opened by Frankstar 0
  • not DPI aware

    not DPI aware

    Modern monitors may have a DPI much higher than 96, but unless an application tells Windows that it knows that, Windows assumes the application believes the DPI to be 96 and does some stretching . That means that you can have your resolution set to 1920x1080 and mouse.get_position() will still report the bottom right as (1535, 863).

    The solution is ctypes.windll.shcore.SetProcessDpiAwareness(2). Users of this library could import ctypes and set this in the application code themselves, but it would probably be better to put it into _winmouse.py.

    opened by snoyes 3
  • Is there a way to detect either up or down mouse wheel scrolling?

    Is there a way to detect either up or down mouse wheel scrolling?

    I am writing a script that needs to be triggered by each scroll up and down.

    mode = int(mode)
    if mode == 1:
        a_key = 1
        b_key = #scroll down
    elif mode == 2:
        a_key = -1
        b_key = #scroll up
    else:
        sys.exit()
    
    while True:
        if keyboard.is_pressed(key)
            while a < 30:
                mouse.wheel(a_key)
                time.sleep(1)
        if |**scroll detect**| (b_key)
            while a < 30:
                mouse.wheel(a_key)
                time.sleep(1)
    

    The full script looks like this I want to detect the top and bottom at this "Scroll detect" part. Since it is not allowed to scroll in the same direction as a_key, we can use other modules than the mouse module, but we prefer the mouse module as much as possible. Please help me.

    opened by YuATools 0
  • Docker support

    Docker support

    I would like to package an application that can access mouse movement as a docker container. It is possible to pass many other devices (webcams etc) to docker by mounting them as volumes/devices. Unfortunately, when I attempt that here, I receive a seg fault, but cannot determine how to troubleshoot it.

    Why docker? It is an easy way to develop on any machine, and then test/deploy anywhere.

    Reproducing the issue This can easily be reproduced by creating the following files:

    # main.py
    import mouse
    print(mouse.get_position())
    
    # Dockerfile
    FROM python:3.9.13
    WORKDIR /app
    RUN pip3 install mouse
    COPY main.py ./
    CMD [ "python", "./main.py"]
    
    # docker-compose.yaml
    version: "3.3"
    services:
      pymouse:
        build: .
        privileged: true
        devices:
          - /dev/mouse0
    

    Then simply run docker-compose up and the app will exit with code 139 (128+ 11) The log shows Segmentation fault (core dumped)

    When I run dmesg, I see the following:

    [ 7377.836267] python3[21490]: segfault at e0 ip 00007f2db4688000 sp 00007ffcf9085a98 error 4 in libX11.so.6.4.0[7f2db4672000+8c000]
    [ 7377.836278] Code: 07 48 03 b7 e8 00 00 00 48 8b 46 10 c3 66 66 2e 0f 1f 84 00 00 00 00 00 66 90 8b 87 e0 00 00 00 c3 66 0f 1f 84 00 00 00 00 00 <48> 63 87 e0 00 00 00 48 c1 e0 07 48 03 87 e8 00 00 00 48 8b 40 10
    

    Any thoughts on how to investigate this? Thanks

    opened by day1118 0
Releases(v0.7.1)
Owner
BoppreH
BoppreH
NYCT-GTFS - Real-time NYC subway data parsing for humans

NYCT-GTFS - Real-time NYC subway data parsing for humans This python library provides a human-friendly, native python interface for dealing with the N

Andrew Dickinson 37 Dec 27, 2022
A ch341dll Wrap is for using in Python 32bits windows to access I2C SPI and MDIO (by GPIO), and Demo with display PC sreen on OLED by i2c or SPI .

ch341dll_wrap_typcal_app A ch341dll Wrap is for using in Python 32bits windows to access I2C SPI and MDIO (by GPIO). In addition, I provided 3 Demo. I

13 Jan 02, 2023
CPU benchmark by calculating Pi, powered by Python3

cpu-benchmark Info: CPU benchmark by calculating Pi, powered by Python 3. Algorithm The program calculates pi with an accuracy of 10,000 decimal place

Alex Dedyura 20 Jan 03, 2023
A Python class for controlling the Pimoroni RGB Keypad for Raspberry Pi Pico

rgbkeypad A Python class for controlling the Pimoroni RGB Keypad for the Raspberry Pi Pico. Compatible with MicroPython and CircuitPython. keypad = RG

Martin O'Hanlon 43 Nov 11, 2022
Pure micropython ESP32 SPI driver for sdcard and screen at the same SPI bus

micropython-esp32-spi-sdcard-and-screen-driver Proof of concept of Pure micropython espidf SPI driver for sdcard with screen at the same SPI bus (exam

Thomas Favennec 7 Mar 14, 2022
CircuitPython library for the CH559 USB to Serial chip

CH559 (USB to Serial) CircuitPython Library Why? Because you might want to get keyboard/mouse/gamepad/HID input into your CircuitPython projects witho

Guy Dupont 3 Nov 19, 2022
Simple python3 implementation of microKanren with lots of type annotations for clarity

MicroKanren-py This is (yet another) python implementation of microKanren. It's a reasonably 1:1 translation of the code provided in the paper, but ev

Erik Derohanian 3 Dec 10, 2022
ESP32 recording button presses, and serving webpage that graphs the numbers over time.

ESP32-IoT-button-graph-test ESP32 recording button presses, and serving webpage via webSockets in order to graph the responses. The objective was to t

f-caro 1 Nov 30, 2021
Custom component for interacting with Octopus Energy

Home Assistant Octopus Energy ** WARNING: This component is currently a work in progress ** Custom component built from the ground up to bring your Oc

David Kendall 116 Jan 02, 2023
I made this so I can control my Tapo L510 light bulb and Govee H6159 light strip using the PyP100 module and the Govee public API

TAPO-And-Govee-Controller I made this so I can control my Tapo L510 light bulb and Govee H6159 light strip using the PyP100 module and the Govee publi

James Westhead 0 Nov 23, 2021
ok-system-helper是一个简单的系统硬件的实时信息收集工具,使用python3.x开发

ok-system-helper ok-system-helper是一个简单的系统硬件的实时信息收集工具,使用python3.x开发,支持哪些硬件:CPU、内存、SWAP、磁盘、网卡流量。用户可在自己的项目中直接引入、开箱即用,或者结合flask等web框架轻松做成http接口供前端调用,亦可通过注

xlvchao 1 Feb 08, 2022
Projet d'integration SRI 3A ROS

projet-integration-sri-2021-2022 Projet d'intégration ROS SRI 2021 2022 Organization: Planification de tâches Perception Saisie: Cédérick Mouliets Sim

AIP Primeca Occitanie 3 Jan 07, 2022
The ABR Control library is a python package for the control and path planning of robotic arms in real or simulated environments.

The ABR Control library is a python package for the control and path planning of robotic arms in real or simulated environments. ABR Control provides API's for the Mujoco, CoppeliaSim (formerly known

Applied Brain Research 277 Jan 05, 2023
This Home Assistant custom component adding support for controlling Midea dehumidifiers on local network.

This custom component for Home Assistant adds support for Midea air conditioner and dehumidifier appliances via the local area network. homeassistant-

Nenad Bogojevic 92 Dec 31, 2022
Real-time Coastal Monitoring at the University of Hawaii at Manoa

Coastal Monitoring at the University of Manoa Source code for Beaglebone/RPi-based data loggers, shore internet gateways, and web server. Software dev

Stanley Lio 7 Dec 07, 2021
LT-OCF: Learnable-Time ODE-based Collaborative Filtering, CIKM'21

LT-OCF: Learnable-Time ODE-based Collaborative Filtering Our proposed LT-OCF Our proposed dual co-evolving ODE Setup Python environment for LT-OCF Ins

Jeongwhan Choi 15 Dec 28, 2022
HomeAssistant - Polyaire AirTouch 4 Integration

HomeAssistant - Polyaire AirTouch 4 Integration Custom integration to add an AirTouch 4 AC Controller Installation: Copy contents of custom_components

7 Aug 05, 2022
The robot is an autonomous small scale racing car using NVIDIA Jetson Nano.

The robot is an autonomous small scale racing car using NVIDIA Jetson Nano. This project utilizes deep learning neural network framework Keras/Tensorflow, together with computer vision library OpenCV

1 Dec 08, 2021
Minimal and clean dashboard to visualize some stats of Pi-Hole with an E-Ink display attached to your Raspberry Pi

Clean Dashboard for Pi-Hole Minimal and clean dashboard to visualize some stats of Pi-Hole with an E-Ink display attached to your Raspberry Pi.

Alessio Santoru 104 Dec 14, 2022
PyTorch implementation of paper "MT-ORL: Multi-Task Occlusion Relationship Learning" (ICCV 2021)

MT-ORL: Multi-Task Occlusion Relationship Learning Official implementation of paper "MT-ORL: Multi-Task Occlusion Relationship Learning" (ICCV 2021) P

Panhe Feng 12 Oct 11, 2022