diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d783b9f --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright © 2015-2017 Martin Tournoij + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +The software is provided "as is", without warranty of any kind, express or +implied, including but not limited to the warranties of merchantability, +fitness for a particular purpose and noninfringement. In no event shall the +authors or copyright holders be liable for any claim, damages or other +liability, whether in an action of contract, tort or otherwise, arising +from, out of or in connection with the software or the use or other dealings +in the software. diff --git a/Makefile b/Makefile index adccd4a..6ee668c 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ all: - cc find-cursor.c -o find-cursor -lX11 + cc find-cursor.c -o find-cursor -lX11 -lXext -lXfixes install: install --strip -o root -g root find-cursor /bin/ diff --git a/README.markdown b/README.markdown index 0ab4201..48a725a 100644 --- a/README.markdown +++ b/README.markdown @@ -1,6 +1,4 @@ -Project status: stable - ------------------------------------------ +[![This project is considered stable](https://img.shields.io/badge/Status-stable-green.svg)](https://arp242.net/status/stable) Simple XLib program to highlight the cursor position. This is similar to the feature found in Windows XP (and possibly later?) diff --git a/find-cursor.c b/find-cursor.c index e97f439..eae1799 100644 --- a/find-cursor.c +++ b/find-cursor.c @@ -1,6 +1,6 @@ /* * http://code.arp242.net/find-cursor - * Copyright © 2015-2016 Martin Tournoij + * Copyright © 2015-2017 Martin Tournoij * See below for full copyright */ @@ -11,22 +11,17 @@ #include #include - #include #include #include - -#include #include #include #include - void usage(char *name); -int get_num(int ch, char *opt, char *name); +int parse_num(int ch, char *opt, char *name); void draw(char *name, int size, int step, int speed, int line_width, char *color_name); - static struct option longopts[] = { {"help", no_argument, NULL, 'h'}, {"size", required_argument, NULL, 's'}, @@ -37,7 +32,6 @@ static struct option longopts[] = { {NULL, 0, NULL, 0} }; - void usage(char *name) { printf("Usage: %s [-stplc]\n\n", name); printf(" -h, --help Show this help.\n"); @@ -54,8 +48,8 @@ void usage(char *name) { printf("\n"); } - -int get_num(int ch, char *opt, char *name) { +// Parse number from commandline, or show error and exit if it's not a number. +int parse_num(int ch, char *opt, char *name) { char *end; long result = strtol(optarg, &end, 10); if (*end) { @@ -79,20 +73,19 @@ int main(int argc, char* argv[]) { while ((ch = getopt_long(argc, argv, "hs:t:p:l:c:r:", longopts, NULL)) != -1) switch (ch) { case 's': - size = get_num(ch, optarg, argv[0]); + size = parse_num(ch, optarg, argv[0]); break; case 't': - step = get_num(ch, optarg, argv[0]); + step = parse_num(ch, optarg, argv[0]); break; case 'p': - speed = get_num(ch, optarg, argv[0]); + speed = parse_num(ch, optarg, argv[0]); break; case 'l': - line_width = get_num(ch, optarg, argv[0]); + line_width = parse_num(ch, optarg, argv[0]); break; case 'c': strncpy(color_name, optarg, sizeof(color_name)); - printf("c: %s\n", color_name); break; case 'h': usage(argv[0]); @@ -108,7 +101,6 @@ int main(int argc, char* argv[]) { draw(argv[0], size, step, speed, line_width, color_name); } - void draw(char *name, int size, int step, int speed, int line_width, char *color_name) { // Setup display and such char *display_name = getenv("DISPLAY"); @@ -120,6 +112,12 @@ void draw(char *name, int size, int step, int speed, int line_width, char *color Display *display = XOpenDisplay(display_name); int screen = DefaultScreen(display); + int shape_event_base, shape_error_base; + if (!XShapeQueryExtension(display, &shape_event_base, &shape_error_base)) { + fprintf(stderr, "%s: no XShape extension for display '%s'\n", name, display_name); + exit(1); + } + // Get the mouse cursor position int win_x, win_y, root_x, root_y = 0; unsigned int mask = 0; @@ -134,13 +132,37 @@ void draw(char *name, int size, int step, int speed, int line_width, char *color Window window = XCreateWindow(display, XRootWindow(display, screen), root_x - size/2, root_y - size/2, // x, y position size, size, // width, height - 0, // border width + 4, // border width DefaultDepth(display, screen), // depth CopyFromParent, // class DefaultVisual(display, screen), // visual CWOverrideRedirect, // valuemask &window_attr // attributes ); + + // Make round shaped window. + XGCValues xgcv; + Pixmap shape_mask = XCreatePixmap(display, window, size, size, 1); + GC part_shape = XCreateGC(display, shape_mask, 0, &xgcv); + XSetForeground(display, part_shape, 0); + XFillRectangle(display, shape_mask, part_shape, 0, 0, size, size); + XSetForeground(display, part_shape, 1); + XFillArc(display, shape_mask, part_shape, + 0, 0, // x, y position + size, size, // Size + 0, 360 * 64); // Make it a full circle + + XShapeCombineMask(display, window, ShapeBounding, 0,0, shape_mask, ShapeSet); + XShapeCombineMask(display, window, ShapeClip, 0,0, shape_mask, ShapeSet); + XFreePixmap(display, shape_mask); + + // Input region is small so we can pass input events. + XRectangle rect; + XserverRegion region = XFixesCreateRegion(display, &rect, 1); + XFixesSetWindowShapeRegion(display, window, ShapeInput, 0, 0, region); + XFixesDestroyRegion(display, region); + + // Set attrs XMapWindow(display, window); XStoreName(display, window, "find-cursor"); @@ -162,14 +184,13 @@ void draw(char *name, int size, int step, int speed, int line_width, char *color e.xclient.data.l[1] = XInternAtom(display, "_NET_WM_STATE_STAYS_ON_TOP", False); XSendEvent(display, XRootWindow(display, screen), False, SubstructureRedirectMask, &e); - // Setting this makes sure compositing window managers don't apply - // shadows and such + // Make sure compositing window managers don't apply shadows and such. // https://specifications.freedesktop.org/wm-spec/1.4/ar01s05.html // https://wiki.archlinux.org/index.php/Compton Atom type_util = XInternAtom(display, "_NET_WM_WINDOW_TYPE", 0); Atom type = XInternAtom(display, "_NET_WM_WINDOW_TYPE_MENU", 0); - XChangeProperty(display, window, type, - XA_ATOM, 32, PropModeReplace, (unsigned char *)&type_util, 1); + XChangeProperty(display, window, type, XA_ATOM, 32, PropModeReplace, + (unsigned char *)&type_util, 1); XRaiseWindow(display, window); XFlush(display); @@ -195,6 +216,7 @@ void draw(char *name, int size, int step, int speed, int line_width, char *color XSync(display, False); usleep(speed * 100); } + XFreeGC(display, gc); XCloseDisplay(display); } @@ -202,19 +224,19 @@ void draw(char *name, int size, int step, int speed, int line_width, char *color /* * The MIT License (MIT) - * - * Copyright © 2015-2016 Martin Tournoij - * + * + * Copyright © 2015-2017 Martin Tournoij + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * The software is provided "as is", without warranty of any kind, express or * implied, including but not limited to the warranties of merchantability, * fitness for a particular purpose and noninfringement. In no event shall the