Skip to content

Instantly share code, notes, and snippets.

@kulp
Created October 5, 2011 15:04
Show Gist options
  • Save kulp/1264657 to your computer and use it in GitHub Desktop.
Save kulp/1264657 to your computer and use it in GitHub Desktop.
Moves the mouse pointer between screens on an X11 display
/**
* @file
* @brief Moves the mouse pointer between screens on an X11 display.
*
* This program might be useful to you if you wish to switch between two X11
* screens without moving your hands from the keyboard. I configure bbkeys to
* map the otherwise-unused windows keys and right-click key to move to the left
* screen, move to the right screen, and toggle between screens, respectively.
*
* Run with zero to three arguments (additional arguments are ignored). The
* first argument is taken as an integer specifying the screen number on which
* to place the mouse cursor in the center of the screen under the display
* specified by the DISPLAY environment variable. If there is no first argument
* or if the first argument is negative, the screen number is chosen by taking
* the screen number parsed from DISPLAY (e.g., screen 1 if DISPLAY = ":0.1")
* and setting the new value to (current - arg1) % number_of_screens. The
* optional second and third arguments specify the x and y coordinates of the
* mouse cursor (defaulting to the center of the screen). Absolute coordinates
* are used by default; relative coordinates are accepted when an argument
* begins with '+' or '-'. Relative and absolute arguments cannot be mixed, but
* this effect can sometimes be acheived by making multiple calls to moveptr.
* Relative cursor movements can be made only on the current display, so the
* screen parameter is ignored.
*
* As a special case, if the screen number (first argument) is negative zero
* (-0), the current screen is used for cursor positioning.
*
* This code is in the public domain. Originally written by Darren Kulp in 2009.
*
* @return Exits with return code 1 if the display cannot be opened, with return
* code 2 if the XTEST extension is not supported, with return code 3 if the
* motion event failed, with return code 4 if an argument parsing error
* occurred, with return code 5 if a miscellaneous error occurred, or with
* return code 0 if the operation appeared to complete successfully.
*/
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/extensions/XTest.h>
int main(int argc, char *argv[])
{
enum { SUCCESS, CANT_OPEN, NO_XTEST, MOTION_FAILED, BAD_ARGS, MISC_ERROR };
Display* dpy = XOpenDisplay(NULL);
if (!dpy)
return CANT_OPEN;
{
int trash;
int ext = XTestQueryExtension(dpy, &trash, &trash, &trash, &trash);
if (!ext)
return NO_XTEST;
}
int screen = -1;
int screenset = 0;
char *check;
if (argc > 1) {
screenset = 1;
screen = strtol(argv[1], &check, 0);
if (check == argv[1])
return BAD_ARGS;
else if (screen == 0 && argv[1][0] == '-')
screen = -1;
}
if (!screenset) {
char* curr = getenv("DISPLAY");
if (!curr)
return MISC_ERROR;
curr = strrchr(curr, '.') + 1;
screen = (strtol(curr, &check, 0) - screen) % ScreenCount(dpy);
if (check == curr)
return BAD_ARGS;
}
int width = DisplayWidth(dpy, screen);
int height = DisplayHeight(dpy, screen);
int x = 0;
int y = 0;
int xset = 0;
int yset = 0;
int relative = 0;
switch (argc) {
default:
case 4:
relative |= (argv[3][0] == '-' || argv[3][0] == '+');
y = strtol(argv[3], &check, 0);
yset = 1;
if (check == argv[3])
return BAD_ARGS;
case 3:
relative |= (argv[2][0] == '-' || argv[2][0] == '+');
x = strtol(argv[2], &check, 0);
xset = 1;
if (check == argv[2])
return BAD_ARGS;
case 2:
case 1:
case 0:
break;
}
if (!relative) {
if (!xset) x = width >> 1;
if (!yset) y = height >> 1;
}
Status rc = relative
? XTestFakeRelativeMotionEvent(dpy, x, y, CurrentTime)
: XTestFakeMotionEvent(dpy, screen, x, y, CurrentTime);
if (!rc)
return MOTION_FAILED;
rc = XCloseDisplay(dpy);
if (!rc)
return MISC_ERROR;
return SUCCESS;
}
/* vi:set ts=4 sw=4 et syntax=c.doxygen: */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment