Centre on the mouse hotspot better

Use xhot and yhot to better get the "mouse hotspot". This should fix #15
pull/19/head
Martin Tournoij 4 years ago
parent a22d1d1f0d
commit 21d69a8223
No known key found for this signature in database
GPG Key ID: A6258419189EE585

@ -50,11 +50,11 @@ Maximum size the circle will grow to.
.TP .TP
\fB-t\fR, \fB--transparent\fR \fB-t\fR, \fB--transparent\fR
Make the window truly 'transparent'. This helps with some display issues when Make the window truly 'transparent'. This helps with some display issues when
following the cursor position, but it doesn't work well with all WMs, which is following the cursor position, but it doesn't work well with all window
why it's disabled by default. managers, which is why it's disabled by default.
.TP .TP
\fB-w\fR, \fB--wait\fR \fI\,MICROSECONDS\/\fR \fB-w\fR, \fB--wait\fR \fI\,TIME\/\fR
Time to wait before drawing the next circle. Time to wait before drawing the next circle, in tenths of milliseconds.
.TP .TP
\fB-r\fR, \fB--repeat\fR \fI\,N\/\fR \fB-r\fR, \fB--repeat\fR \fI\,N\/\fR
Number of times to repeat the animation. Use 0 to repeat indefinitely. Number of times to repeat the animation. Use 0 to repeat indefinitely.
@ -78,7 +78,7 @@ find-cursor --repeat 0 --follow --distance 1 --wait 1 --line-width 16 --size 16
.PP .PP
You will want to map a key in your window manager to run \fIfind-cursor\fR. You You will want to map a key in your window manager to run \fIfind-cursor\fR. You
can also use \fIxbindkeys\fR, which should work with $any window manager. can also use \fIxbindkeys\fR, which should work with any window manager.
.PP .PP
I run it with \fIxcape\fR: I run it with \fIxcape\fR:
.RS .RS

@ -1,6 +1,6 @@
/* /*
* http://code.arp242.net/find-cursor * http://code.arp242.net/find-cursor
* Copyright © 2015-2017 Martin Tournoij <martin@arp242.net> * Copyright © 2015-2020 Martin Tournoij <martin@arp242.net>
* See below for full copyright * See below for full copyright
*/ */
@ -22,8 +22,7 @@
void usage(char *name); void usage(char *name);
int parse_num(int ch, char *opt, char *name); int parse_num(int ch, char *opt, char *name);
void draw( void draw(char *name, Display *display, int screen,
char *name, Display *display, int screen,
int size, int distance, int wait, int line_width, char *color_name, int size, int distance, int wait, int line_width, char *color_name,
int follow, int transparent, int grow, int outline, int repeat); int follow, int transparent, int grow, int outline, int repeat);
@ -43,7 +42,9 @@ static struct option longopts[] = {
}; };
void usage(char *name) { void usage(char *name) {
printf("Usage: %s [-stplcftgr]\n\n", name); printf("Usage: %s [-stplcftgr]\n", name);
printf("\n");
printf("Flags:\n");
printf(" -h, --help Show this help.\n"); printf(" -h, --help Show this help.\n");
printf("\n"); printf("\n");
printf("Shape options:\n"); printf("Shape options:\n");
@ -51,8 +52,8 @@ void usage(char *name) {
printf(" -d, --distance Distance between the circles in pixels.\n"); printf(" -d, --distance Distance between the circles in pixels.\n");
printf(" -l, --line-width Width of the lines in pixels.\n"); printf(" -l, --line-width Width of the lines in pixels.\n");
printf(" -w, --wait Time to wait before drawing the next circle in\n"); printf(" -w, --wait Time to wait before drawing the next circle in\n");
printf(" microseconds.\n"); printf(" tenths of milliseconds.\n");
printf(" -c, --color Color; can either be an X11 color name or RGB as hex.\n"); printf(" -c, --color Color as X11 color name or RGB (e.g. #ff0000)\n");
printf(" -g, --grow Grow the animation in size, rather than shrinking it.\n"); printf(" -g, --grow Grow the animation in size, rather than shrinking it.\n");
printf("\n"); printf("\n");
printf("Extra options:\n"); printf("Extra options:\n");
@ -68,12 +69,11 @@ void usage(char *name) {
printf("\n"); printf("\n");
printf("Examples:\n"); printf("Examples:\n");
printf(" The defaults:\n"); printf(" The defaults:\n");
printf(" %s --size 320 --distance 40 --wait 400 --line-width 4 --color black\n\n", name); printf(" %s --size 320 --distance 40 --wait 400 --line-width 4 --color black\n\n", name);
printf(" Draw a solid circle:\n"); printf(" Draw a solid circle:\n");
printf(" %s --size 100 --distance 1 --wait 20 --line-width 1\n\n", name); printf(" %s --size 100 --distance 1 --wait 20 --line-width 1\n\n", name);
printf(" Always draw a full circle on top of the cursor:\n"); printf(" Always draw a full circle on top of the cursor:\n");
printf(" %s --repeat 0 --follow --distance 1 --wait 1 --line-width 16 --size 16", name); printf(" %s --repeat 0 --follow --distance 1 --wait 1 --line-width 16 --size 16\n", name);
printf("\n");
} }
// Parse number from commandline, or show error and exit if it's not a number. // Parse number from commandline, or show error and exit if it's not a number.
@ -88,7 +88,6 @@ int parse_num(int ch, char *opt, char *name) {
return result; return result;
} }
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
// Parse options // Parse options
int size = 320; int size = 320;
@ -166,22 +165,29 @@ int main(int argc, char* argv[]) {
} }
// Actually draw. // Actually draw.
do { do
draw(argv[0], display, screen, draw(argv[0], display, screen,
size, distance, wait, line_width, color_name, size, distance, wait, line_width, color_name,
follow, transparent, grow, outline, repeat); follow, transparent, grow, outline, repeat);
} while (repeat == -1 || repeat--); while (repeat == -1 || repeat--);
XCloseDisplay(display); XCloseDisplay(display);
} }
void draw( // Try to get the centre of the cursor.
char *name, Display *display, int screen, void cursor_center(Display *display, int size, int *x, int *y) {
XFixesCursorImage *c = XFixesGetCursorImage(display);
*x = c->x - size/2 - c->width/2 + c->xhot;
*y = c->y - size/2 - c->height/2 + c->yhot;
}
void draw(char *name, Display *display, int screen,
int size, int distance, int wait, int line_width, char *color_name, int size, int distance, int wait, int line_width, char *color_name,
int follow, int transparent, int grow, int outline, int repeat int follow, int transparent, int grow, int outline, int repeat
) { ) {
// Get the mouse cursor position and size. // Get the mouse cursor position and size.
XFixesCursorImage *cursor = XFixesGetCursorImage(display); int center_x, center_y;
cursor_center(display, size, &center_x, &center_y);
// Create a window at the mouse position // Create a window at the mouse position
Window window; Window window;
@ -194,8 +200,8 @@ void draw(
window_attr.colormap = XCreateColormap(display, DefaultRootWindow(display), vinfo.visual, AllocNone); window_attr.colormap = XCreateColormap(display, DefaultRootWindow(display), vinfo.visual, AllocNone);
window_attr.background_pixel = 0; window_attr.background_pixel = 0;
window = XCreateWindow(display, XRootWindow(display, screen), window = XCreateWindow(display, XRootWindow(display, screen),
cursor->x - size/2 - cursor->width/2, // x position center_x, // x position
cursor->y - size/2 - cursor->height/2, // y position center_y, // y position
size, size, // width, height size, size, // width, height
4, // border width 4, // border width
vinfo.depth, // depth vinfo.depth, // depth
@ -204,10 +210,10 @@ void draw(
CWColormap | CWBorderPixel | CWBackPixel | CWOverrideRedirect, // valuemask CWColormap | CWBorderPixel | CWBackPixel | CWOverrideRedirect, // valuemask
&window_attr); // attributes &window_attr); // attributes
} }
else { else
window = XCreateWindow(display, XRootWindow(display, screen), window = XCreateWindow(display, XRootWindow(display, screen),
cursor->x - size/2 - cursor->width/2, // x position center_x, // x position
cursor->y - size/2 - cursor->height/2, // y position center_y, // y position
size, size, // width, height size, size, // width, height
4, // border width 4, // border width
DefaultDepth(display, screen), // depth DefaultDepth(display, screen), // depth
@ -215,7 +221,6 @@ void draw(
DefaultVisual(display, screen), // visual DefaultVisual(display, screen), // visual
CWOverrideRedirect, // valuemask CWOverrideRedirect, // valuemask
&window_attr); // attributes &window_attr); // attributes
}
// Make round shaped window. // Make round shaped window.
XGCValues xgcv; XGCValues xgcv;
@ -229,8 +234,8 @@ void draw(
size, size, // Size size, size, // Size
0, 360 * 64); // Make it a full circle 0, 360 * 64); // Make it a full circle
XShapeCombineMask(display, window, ShapeBounding, 0,0, shape_mask, ShapeSet); XShapeCombineMask(display, window, ShapeBounding, 0, 0, shape_mask, ShapeSet);
XShapeCombineMask(display, window, ShapeClip, 0,0, shape_mask, ShapeSet); XShapeCombineMask(display, window, ShapeClip, 0, 0, shape_mask, ShapeSet);
XFreePixmap(display, shape_mask); XFreePixmap(display, shape_mask);
// Input region is small so we can pass input events. // Input region is small so we can pass input events.
@ -288,9 +293,10 @@ void draw(
color2.red = 65535 - color.red; color2.red = 65535 - color.red;
color2.green = 65535 - color.green; color2.green = 65535 - color.green;
color2.blue = 65535 - color.blue; color2.blue = 65535 - color.blue;
sprintf(color2_name,"#%04X%04X%04X", color2.red,color2.green, color2.blue); sprintf(color2_name, "#%04X%04X%04X", color2.red, color2.green, color2.blue);
XAllocNamedColor(display, colormap, color2_name, &color2, &color2); XAllocNamedColor(display, colormap, color2_name, &color2, &color2);
} else { }
else {
// Set colour only once if not outline. // Set colour only once if not outline.
XSetLineAttributes(display, gc, line_width, LineSolid, CapButt, JoinBevel); XSetLineAttributes(display, gc, line_width, LineSolid, CapButt, JoinBevel);
XSetForeground(display, gc, color.pixel); XSetForeground(display, gc, color.pixel);
@ -299,15 +305,10 @@ void draw(
// Draw the circles // Draw the circles
int i = 1; int i = 1;
for (i=1; i<=size; i+=distance) { for (i=1; i<=size; i+=distance) {
if (follow) { if (follow)
XClearWindow(display, window); XClearWindow(display, window);
}
int cs; int cs = grow ? i : size - i;
if (grow)
cs = i;
else
cs = size - i;
if (outline) { if (outline) {
XSetLineAttributes(display, gc, line_width+2, LineSolid, CapButt, JoinBevel); XSetLineAttributes(display, gc, line_width+2, LineSolid, CapButt, JoinBevel);
@ -328,10 +329,8 @@ void draw(
0, 360 * 64); // Make it a full circle 0, 360 * 64); // Make it a full circle
if (follow) { if (follow) {
XFixesCursorImage *cursor = XFixesGetCursorImage(display); cursor_center(display, size, &center_x, &center_y);
XMoveWindow(display, window, XMoveWindow(display, window, center_x, center_y);
cursor->x - size/2 - cursor->width/2,
cursor->y - size/2 - cursor->height/2);
} }
XSync(display, False); XSync(display, False);
@ -346,7 +345,7 @@ void draw(
/* /*
* The MIT License (MIT) * The MIT License (MIT)
* *
* Copyright © 2015-2017 Martin Tournoij * Copyright © 2015-2020 Martin Tournoij
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to * of this software and associated documentation files (the "Software"), to

Loading…
Cancel
Save