Created
October 5, 2011 15:04
-
-
Save kulp/1264657 to your computer and use it in GitHub Desktop.
Moves the mouse pointer between screens on an X11 display
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @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