Skip to content

Instantly share code, notes, and snippets.

@pioz
Last active July 10, 2023 15:24
Show Gist options
  • Save pioz/726474 to your computer and use it in GitHub Desktop.
Save pioz/726474 to your computer and use it in GitHub Desktop.
Autoclick
// Written by Pioz.
// Compile with: gcc -o autoclick autoclick.c -lX11
#include <stdio.h> // printf, fprintf and fflush
#include <string.h> // memset
#include <unistd.h> // sleep and usleep
#include <X11/Xlib.h> // X11
#include <X11/Xutil.h> // XGetPixel and XDestroyImage
// Simulate mouse click
void
click (Display *display, int button)
{
// Create and setting up the event
XEvent event;
memset (&event, 0, sizeof (event));
event.xbutton.button = button;
event.xbutton.same_screen = True;
event.xbutton.subwindow = DefaultRootWindow (display);
while (event.xbutton.subwindow)
{
event.xbutton.window = event.xbutton.subwindow;
XQueryPointer (display, event.xbutton.window,
&event.xbutton.root, &event.xbutton.subwindow,
&event.xbutton.x_root, &event.xbutton.y_root,
&event.xbutton.x, &event.xbutton.y,
&event.xbutton.state);
}
// Press
event.type = ButtonPress;
if (XSendEvent (display, PointerWindow, True, ButtonPressMask, &event) == 0)
fprintf (stderr, "Error to send the event!\n");
XFlush (display);
usleep (1);
// Release
event.type = ButtonRelease;
if (XSendEvent (display, PointerWindow, True, ButtonReleaseMask, &event) == 0)
fprintf (stderr, "Error to send the event!\n");
XFlush (display);
usleep (1);
}
// Get mouse coordinates
void
coords (Display *display, int *x, int *y)
{
XEvent event;
XQueryPointer (display, DefaultRootWindow (display),
&event.xbutton.root, &event.xbutton.window,
&event.xbutton.x_root, &event.xbutton.y_root,
&event.xbutton.x, &event.xbutton.y,
&event.xbutton.state);
*x = event.xbutton.x;
*y = event.xbutton.y;
}
// Move mouse pointer (relative)
void
move (Display *display, int x, int y)
{
XWarpPointer (display, None, None, 0,0,0,0, x, y);
XFlush (display);
usleep (1);
}
// Move mouse pointer (absolute)
void
move_to (Display *display, int x, int y)
{
int cur_x, cur_y;
coords (display, &cur_x, &cur_y);
XWarpPointer (display, None, None, 0,0,0,0, -cur_x, -cur_y);
XWarpPointer (display, None, None, 0,0,0,0, x, y);
usleep (1);
}
// Get pixel color at coordinates x,y
void
pixel_color (Display *display, int x, int y, XColor *color)
{
XImage *image;
image = XGetImage (display, DefaultRootWindow (display), x, y, 1, 1, AllPlanes, XYPixmap);
color->pixel = XGetPixel (image, 0, 0);
XDestroyImage (image);
XQueryColor (display, DefaultColormap(display, DefaultScreen (display)), color);
}
// START HERE
int
main (int argc, char *argv[])
{
int starting = 3;
int x = 0;
int y = 0;
// Open X display
Display *display = XOpenDisplay (NULL);
if (display == NULL)
{
fprintf (stderr, "Can't open display!\n");
return -1;
}
// Wait 3 seconds to start
printf ("Starting in ");
fflush (stdout);
while (starting > 0)
{
printf ("\b\b\b %d...", starting);
fflush (stdout);
sleep (1);
starting--;
}
printf ("\n");
// Start
while (1)
{
click (display, Button1);
//move (display, x, y);
//coords (dispaly, &x, &y);
sleep (1);
}
// Close X display and exit
XCloseDisplay (display);
return 0;
}
@airvzxf
Copy link

airvzxf commented Jun 5, 2011

Hola Agrego otras 2 funciones.

void moveReset() {
int xTmp=0,yTmp=0;
coords(&xTmp, &yTmp);
move(-xTmp, -yTmp);
}

void moveTo(Display *display, int x, int y) {
int xTmp=0,yTmp=0;
coords(&xTmp, &yTmp);
XWarpPointer(display, None, None, 0, 0, 0, 0, -xTmp, -yTmp);
XWarpPointer(display, None, None, 0, 0, 0, 0, x, y);
XFlush(display);
usleep(1);
}

Copy link

ghost commented Jun 8, 2016

Hello,

there is a mem leak:
Line 82: replace XFree (image); with: XDestroyImage (image);

@lucasjinreal
Copy link

click method core dumped

@maztan
Copy link

maztan commented Aug 5, 2019

Thank you so much for this code :)

@schrmh
Copy link

schrmh commented Jan 3, 2020

Hey, Pioz.
This is some very useful code.
Do you know by any chane how to use the XEvents for clicking with another pointer device (that was created by e.g xinput create-master mouse)?

I got this (compile with gcc -lXi -lX11 -lXtst -o test BackgroundMouse.c):

#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
#include <X11/extensions/XTest.h>
int main (int argc, char *argv[])
{
  int delta_x = 500, delta_y = 160;
  Display *display = XOpenDisplay(0);
  Window root = DefaultRootWindow(display);
  XIWarpPointer(display, 14, None, root, 0, 0, 0, 0, delta_x, delta_y);
  XDevice *device = NULL;
  device = XOpenDevice(display, 16);
  XTestFakeDeviceButtonEvent(display, device, 1, True, 0, 0, CurrentTime);
  XTestFakeDeviceButtonEvent(display, device, 1, False, 0, 0, CurrentTime);
  XCloseDisplay(display);
}

but the difference between XTestFakeDeviceButtonEvent and your XEvent code for clicking is that your code can click without giving focus to a window but XTestFakeDeviceButtonEvent gives focus which is not useful for a auto clicker that should run in the background while I use my main virtual pointer for working on different stuff..

@vaizq
Copy link

vaizq commented Aug 28, 2021

Thanks for the code, but does anyone have idea why this clicker wont click in chromium browser? It works in desktop apps.

@schrmh
Copy link

schrmh commented Aug 28, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment