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
This repository contains all the code and files needed to simulate the notspot quadrupedal robot using Gazebo and ROS.

Notspot robot simulation - Python version This repository contains all the files and code needed to simulate the notspot quadrupedal robot using Gazeb

50 Sep 26, 2022
E-Ink Magic Calendar that automatically syncs to Google Calendar and runs off a battery powered Raspberry Pi Zero

E-Ink Magic Calendar that automatically syncs to Google Calendar and runs off a battery powered Raspberry Pi Zero

2.8k Dec 30, 2022
Ingeniamotion is a library that works over ingenialink and aims to simplify the interaction with Ingenia's drives.

Ingeniamotion Ingeniamotion is a library that works over ingenialink and aims to simplify the interaction with Ingenia's drives. Requirements Python 3

Ingenia Motion Control 7 Dec 15, 2022
A python script for macOS to enable scrolling with the 3M ergonomic mouse EM500GPS in any application.

A python script for macOS to enable scrolling with the 3M ergonomic mouse EM500GPS in any application.

3 Feb 19, 2022
🐱 Petkit feeder components for HomeAssistant

Petkit for HomeAssistant Installing Download and copy custom_components/xiaomi_miot folder to custom_components folder in your HomeAssistant config fo

62 Dec 29, 2022
DNP3 Stalker is a project to analyze and interact with DNP3 devices

DNP3 Stalker Purpose DNP3 Stalker is a project to analyze and interact with DNP3

Cutaway Security, LLC. 2 Feb 10, 2022
The main aim of this project is to avoid the accidents in shredding ( Waste Recycling Industry )

shredder-Machine-Hand-Safety The main aim of this project is to avoid the accidents in shredding ( Waste Recycling Industry ) . The Basic function of

Shubham Chaudhari 1 Nov 15, 2021
A python script for Homeassistant that counts down the days to birthdays, anniversaries etc

Date Countdown A python script for Homeassistant that counts down the days to birthdays, anniversaries etc Important note I no longer use homeassistan

Marc Forth 21 Mar 12, 2022
Volta: A Virtual Assistant which increases your productivity with time as you use it…

Volta Official Documentation Overview & Purpose Volta: A Virtual Assistant which increases your productivity with time as you use it… Volta, developed

Abeer Joshi 1 Jan 14, 2022
Implementation of Forwards Kinematics, Inverse Kinematics, Point to Point Movement and Synchronous movement for Kuka KR 120 R2700-2.

I made this project for my university course in robotics. I rarely found any information regarding the implementation of mathematics in code. So I decided to make this repo in order to help others :)

2 Dec 27, 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
This OctoPrint plugin will make the initial connection to 3D Hub a breeze

3D Hub Connector This OctoPrint plugin will make the initial connection to 3D Hub a breeze. In future it will help in setting up a tunnel connection a

3D Hub 2 Aug 03, 2022
Jarvis: a personal assistant which can help you to manage your system

Jarvis Jarvis is personal AI based assistant which can help you to manage stuff in your computer. This is demo but I decided to make it more better so

2 Jun 02, 2022
Volkswagen ID component for Home Assistant

Volkswagen ID component for Home Assistant This folder contains both a generic Python 3 library for the Volkswagen ID API and a component for Home Ass

55 Jan 07, 2023
3d printable macropad

Pico Mpad A 3D printable macropad for automating frequently repeated actions. Hardware To build this project you need access to a 3d printer. The mode

Dmytro Panin 94 Jan 07, 2023
Open-Source board for converting RaspberryPI to Brain-computer interface

The easiest way to the neuroscience world with the shield for RaspberryPi - PIEEG (website). Open-source. Crowdsupply This project is the result of se

Ildaron 436 Jan 01, 2023
Sensor of Temperature Feels Like for Home Assistant.

Please ⭐ this repo if you find it useful Sensor of Temperature Feels Like for Home Assistant Installation Install from HACS (recommended) Have HACS in

Andrey 60 Dec 25, 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
Fener ROS2 package version 2

Fener's ROS2 codes that runs on the vehicle. This node contains basic sensing and actuation nodes for vehicle control. Also example applications will be added.

Muhammed Sezer 1 Jan 18, 2022
ArduinoWaterHeaterIOT - IoT Probe of a solar PV water heating system - Arduino, Python, MQTT, MySQL

ArduinoWaterHeaterIOT IoT Probe of a solar PV water heating system - Arduino, Raspberry Pi, Python, MQTT, MySQL The Arduino sends the AC and DC watts

Jacques Fourie 1 Jan 11, 2022