mirror of
https://github.com/arp242/find-cursor
synced 2024-11-16 12:13:24 +00:00
Compare commits
36 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
4a67d023ef | ||
|
925afa184f | ||
|
1d99800f94 | ||
|
32f9e7f1d3 | ||
|
11ad767bd4 | ||
|
a78c716475 | ||
|
398e540c44 | ||
|
5fdb707a25 | ||
|
73fcc7d419 | ||
|
49f0ef9270 | ||
|
9ed9ec581c | ||
|
1f32dd7238 | ||
|
cd2a08a96c | ||
|
45e937a7a3 | ||
|
241ae5c0d4 | ||
|
27f1a9699b | ||
|
e2b8ae35da | ||
|
21d69a8223 | ||
|
a22d1d1f0d | ||
|
87d9e18155 | ||
|
79f2a2f504 | ||
|
e222a32479 | ||
|
49edf0b825 | ||
|
49ce340e87 | ||
|
ff7be1dad0 | ||
|
4951ce6718 | ||
|
032ccd0256 | ||
|
ba889debe4 | ||
|
19c99b46b3 | ||
|
db50bc256d | ||
|
fcc5cb2534 | ||
|
222db0fb4d | ||
|
19add1b666 | ||
|
4a92f61bdf | ||
|
eea197fbe1 | ||
|
3d5735acee |
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
||||
github: arp242
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
||||
find-cursor
|
||||
/find-cursor
|
||||
|
@ -1,8 +0,0 @@
|
||||
language: c
|
||||
install: make
|
||||
script: make
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
notifications:
|
||||
email: false
|
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright © 2015-2017 Martin Tournoij
|
||||
Copyright © 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
|
||||
|
21
Makefile
21
Makefile
@ -1,8 +1,21 @@
|
||||
CC?=cc
|
||||
CFLAGS?=-std=c99 -pedantic -Wall -Os
|
||||
CC ?= cc
|
||||
PREFIX ?= /usr/local
|
||||
NAME ?= find-cursor
|
||||
|
||||
CFLAGS += -std=c99 -pedantic -Wall -Wextra -Wpedantic -Os
|
||||
LDFLAGS += -L/usr/lib
|
||||
LIBS += -lX11 -lXext -lXfixes
|
||||
|
||||
.PHONY: all clean install uninstall
|
||||
|
||||
all:
|
||||
${CC} ${CFLAGS} -o find-cursor find-cursor.c -lX11 -lXext -lXfixes
|
||||
${CC} ${CFLAGS} ${LDFLAGS} -o ${NAME} *.c ${LIBS}
|
||||
|
||||
clean:
|
||||
rm -f ${NAME}
|
||||
|
||||
install:
|
||||
install --strip -o root -g root find-cursor /bin/
|
||||
install -Dm755 ${NAME} ${DESTDIR}${PREFIX}/bin/${NAME}
|
||||
|
||||
uninstall:
|
||||
rm -f ${DESTDIR}${PREFIX}/bin/${NAME}
|
||||
|
@ -1,42 +0,0 @@
|
||||
[![This project is considered stable](https://img.shields.io/badge/Status-stable-green.svg)](https://arp242.net/status/stable)
|
||||
[![Build Status](https://travis-ci.org/Carpetsmoker/find-cursor.svg?branch=master)](https://travis-ci.org/Carpetsmoker/find-cursor)
|
||||
|
||||
Simple XLib program to highlight the cursor position. This is similar to the
|
||||
feature found in Windows XP (and possibly later?)
|
||||
|
||||
![screenshot.gif](https://raw.githubusercontent.com/Carpetsmoker/find-cursor/master/screenshot.gif)
|
||||
|
||||
Using it
|
||||
========
|
||||
Compile it by typing `make`. Run `find-cursor -h to see some options for
|
||||
controlling the appearance.
|
||||
|
||||
- The author runs it with [`xcape`][xcape]:
|
||||
|
||||
xcape -e 'Control_L=Escape;Shift_L=KP_Add'
|
||||
|
||||
When Left shift is tapped, a Keypad Add is sent – I don't have a numpad on my
|
||||
keyboard – which we can then use to launch the program.
|
||||
|
||||
- I configured my window manager (PekWM) to pick up Numpad Add and launch this:
|
||||
|
||||
KeyPress = "KP_Add" { Actions = "Exec find-cursor" }
|
||||
|
||||
I'm not going to include instructions for every window manager out there.
|
||||
I'm sure you can figure out how to use it with your WM ;-) You can also use
|
||||
[`xbindkeys`](xbindkeys), which should work with `$any` window manager.
|
||||
|
||||
- You may want to disable shadows if you use compton or some other composite
|
||||
manager; for example for compton start it with:
|
||||
|
||||
compton --shadow-exclude "class_g = 'find-cursor'"
|
||||
|
||||
Or, perhaps even better, disable it for all shaped windows:
|
||||
|
||||
compton --shadow-exclude 'bounding_shaped'
|
||||
|
||||
You can also put that in the compton config file. Other managers might have
|
||||
different options/flags.
|
||||
|
||||
[xcape]: https://github.com/alols/xcape
|
||||
[xbindkeys]: http://www.nongnu.org/xbindkeys/xbindkeys.html
|
70
README.md
Normal file
70
README.md
Normal file
@ -0,0 +1,70 @@
|
||||
Simple XLib program to highlight the cursor position. This is similar to the
|
||||
feature found in Windows XP (and possibly later?)
|
||||
|
||||
![screenshot.gif](https://raw.githubusercontent.com/arp242/find-cursor/master/screenshot.gif)
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Compile it by typing `make`, install it with `make install`. There
|
||||
[packages][pkg] for some platforms as well.
|
||||
|
||||
You'll need to install some X11 header files on some systems; e.g. on
|
||||
Ubuntu/Debian: `libx11-dev`, `libxcomposite-dev`, `libxdamage-dev`, and
|
||||
`libxrender-dev`. For Fedora 36 you might need to install following:
|
||||
`libXext-devel`, `libXdamage-devel`, `libXrender-devel`, `libXext-devel`.
|
||||
|
||||
There is also a Docker container at [klo2k/find-cursor][d] if you want it. Note
|
||||
this is NOT maintained (or supported) by me. See #19.
|
||||
|
||||
[d]: https://hub.docker.com/r/klo2k/find-cursor
|
||||
[pkg]: https://repology.org/project/find-cursor/versions
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
See `find-cursor -h` to see some options for controlling the appearance.
|
||||
|
||||
Launching
|
||||
---------
|
||||
|
||||
You will want to map a key in your window manager to run `find-cursor`. You can
|
||||
also use [`xbindkeys`](xbindkeys), which should work with `$any` window manager.
|
||||
|
||||
I run it with [`xcape`][xcape]:
|
||||
|
||||
xcape -e 'Control_L=Escape;Shift_L=KP_Add'
|
||||
|
||||
When `Left Shift` is tapped a `Keypad Add` is sent; I configured my window
|
||||
manager to launch `find-cursor` with that.
|
||||
|
||||
I don't have a numpad on my keyboard; you can also use `F13` or some other
|
||||
unused key.
|
||||
|
||||
You can use a little wrapper script if you want a "toggle" switch for when
|
||||
repeating forever:
|
||||
|
||||
#!/bin/sh
|
||||
if pgrep find-cursor; then
|
||||
pkill find-cursor
|
||||
else
|
||||
find-cursor -r0 &
|
||||
fi
|
||||
|
||||
Compton
|
||||
-------
|
||||
|
||||
You may want to disable shadows if you use compton or some other composite
|
||||
manager; for example for compton start it with:
|
||||
|
||||
compton --shadow-exclude "class_g = 'find-cursor'"
|
||||
|
||||
Or, perhaps even better, disable it for all shaped windows:
|
||||
|
||||
compton --shadow-exclude 'bounding_shaped'
|
||||
|
||||
You can also put that in the compton config file. Other managers might have
|
||||
different options/flags.
|
||||
|
||||
[xcape]: https://github.com/alols/xcape
|
||||
[xbindkeys]: http://www.nongnu.org/xbindkeys/xbindkeys.html
|
352
find-cursor.c
352
find-cursor.c
@ -1,10 +1,10 @@
|
||||
/*
|
||||
* http://code.arp242.net/find-cursor
|
||||
* Copyright © 2015-2017 Martin Tournoij <martin@arp242.net>
|
||||
* Copyright © Martin Tournoij <martin@arp242.net>
|
||||
* See below for full copyright
|
||||
*/
|
||||
|
||||
#define _XOPEN_SOURCE 500
|
||||
#define _DEFAULT_SOURCE
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdint.h>
|
||||
@ -22,12 +22,12 @@
|
||||
|
||||
void usage(char *name);
|
||||
int parse_num(int ch, char *opt, char *name);
|
||||
void draw(
|
||||
char *name,
|
||||
int pointer_screen(char *name, Display *display);
|
||||
void draw(char *name, Display *display, int screen,
|
||||
int size, int distance, int wait, int line_width, char *color_name,
|
||||
int follow, int transparent, int grow, int outline);
|
||||
int follow, int transparent, int grow, int outline, char *ocolor_name);
|
||||
|
||||
static struct option longopts[] = {
|
||||
static struct option longopts[] = {
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"size", required_argument, NULL, 's'},
|
||||
{"distance", required_argument, NULL, 'd'},
|
||||
@ -37,53 +37,77 @@ static struct option longopts[] = {
|
||||
{"follow", no_argument, NULL, 'f'},
|
||||
{"transparent", no_argument, NULL, 't'},
|
||||
{"grow", no_argument, NULL, 'g'},
|
||||
{"outline", no_argument, NULL, 'o'},
|
||||
{"outline", optional_argument, NULL, 'o'}, // Optional for compat, as previously it was hard-coded to 2px.
|
||||
{"repeat", required_argument, NULL, 'r'},
|
||||
{"outline-color", required_argument, NULL, 'O'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
};
|
||||
|
||||
void usage(char *name) {
|
||||
printf("Usage: %s [-stplcftg]\n\n", name);
|
||||
printf(" -h, --help Show this help.\n");
|
||||
printf("\n");
|
||||
printf("Shape options:\n");
|
||||
printf(" -s, --size Maximum size the circle will grow to 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(" -w, --wait Time to wait before drawing the next circle in\n");
|
||||
printf(" microseconds.\n");
|
||||
printf(" -c, --color Color; can either be an X11 color name or RGB as hex.\n");
|
||||
printf(" -g, --grow Grow the animation in size, rather than shrinking it.\n");
|
||||
printf("\n");
|
||||
printf("Extra options:\n");
|
||||
printf(" -f, --follow Follow the cursor position as the cursor is moving.\n");
|
||||
printf(" -t, --transparent Make the window truly 'transparent'. This helps with\n");
|
||||
printf(" some display issues when following the cursor position,\n");
|
||||
printf(" but it doesn't work well with all WMs, which is why\n");
|
||||
printf(" it's disabled by default.\n");
|
||||
printf(" -o, --outline Draw an outline in the opposite color as well. Helps\n");
|
||||
printf(" visibility on all backgrounds.\n");
|
||||
printf("\n");
|
||||
printf("Examples:\n");
|
||||
printf(" The defaults:\n");
|
||||
printf(" %s --size 320 --distance 40 --wait 400 --line-width 4 --color black\n\n", name);
|
||||
printf(" Draw a solid circle:\n");
|
||||
printf(" %s --size 100 --distance 1 --wait 20 --line-width 1\n", name);
|
||||
printf("\n");
|
||||
printf(""
|
||||
"find-cursor highlights the cursor position by drawing circles around it.\n"
|
||||
"https://github.com/arp242/find-cursor\n"
|
||||
"\n"
|
||||
"Flags:\n"
|
||||
" -h, --help Show this help.\n"
|
||||
"\n"
|
||||
"Shape options:\n"
|
||||
" -s, --size Maximum size the circle will grow to in pixels.\n"
|
||||
" -d, --distance Distance between the circles in pixels.\n"
|
||||
" -l, --line-width Width of the lines in pixels.\n"
|
||||
" -w, --wait Time to wait before drawing the next circle in\n"
|
||||
" tenths of milliseconds.\n"
|
||||
" -c, --color Color as X11 color name or RGB (e.g. #ff0000)\n"
|
||||
" -g, --grow Grow the animation in size, rather than shrinking it.\n"
|
||||
"\n"
|
||||
"Extra options:\n"
|
||||
" -f, --follow Follow the cursor position as the cursor is moving.\n"
|
||||
" -t, --transparent Make the window truly 'transparent'. This helps with\n"
|
||||
" some display issues when following the cursor position,\n"
|
||||
" but it doesn't work well with all WMs, which is why\n"
|
||||
" it's disabled by default.\n"
|
||||
" -o, --outline Width in pixels of outline; uses 2px if no value is given.\n"
|
||||
" Helps visibility on all backgrounds.\n"
|
||||
" -O, --outline-color Color of outline; if omitted it will automatically use\n"
|
||||
" the opposite color. No effect if -o isn't set.\n"
|
||||
" -r, --repeat Number of times to repeat the animation; use 0 to repeat\n"
|
||||
" indefinitely.\n"
|
||||
"\n"
|
||||
"Examples:\n"
|
||||
" The defaults:\n"
|
||||
" %s --size 320 --distance 40 --wait 400 --line-width 4 --color black\n\n"
|
||||
" Draw a solid circle:\n"
|
||||
" %s --size 100 --distance 1 --wait 20 --line-width 1\n\n"
|
||||
" Always draw a full circle on top of the cursor:\n"
|
||||
" %s --repeat 0 --follow --distance 1 --wait 1 --line-width 16 --size 16\n"
|
||||
"\n"
|
||||
"Launching:\n"
|
||||
" You will want to map a key in your window manager to run find-cursor.\n"
|
||||
" You can also use xbindkeys, which should work with any window manager.\n"
|
||||
"\n"
|
||||
" I run it with xcape:\n"
|
||||
" xcape -e 'Control_L=Escape;Shift_L=KP_Add'\n"
|
||||
"\n"
|
||||
" When Left Shift is tapped a Keypad Add is sent; I configured my window\n"
|
||||
" manager to launch find-cursor with that.\n"
|
||||
"\n"
|
||||
" I don't have a numpad on my keyboard; you can also use F13 or some\n"
|
||||
" other unused key.\n",
|
||||
name, name, 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);
|
||||
long result = strtol(opt, &end, 10);
|
||||
if (*end) {
|
||||
fprintf(stderr, "%s: %d must be a number\n", name, ch);
|
||||
fprintf(stderr, "%s: value for -%c must be a number\n\n", name, ch);
|
||||
usage(name);
|
||||
exit(1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// Parse options
|
||||
int size = 320;
|
||||
@ -91,13 +115,16 @@ int main(int argc, char* argv[]) {
|
||||
int wait = 400;
|
||||
int line_width = 4;
|
||||
char color_name[64] = "black";
|
||||
char ocolor_name[64];
|
||||
int follow = 0;
|
||||
int transparent = 0;
|
||||
int grow = 0;
|
||||
int outline = 0;
|
||||
int repeat = 0;
|
||||
|
||||
extern int optopt;
|
||||
int ch;
|
||||
while ((ch = getopt_long(argc, argv, "hs:d:w:l:c:r:ftgo", longopts, NULL)) != -1)
|
||||
while ((ch = getopt_long(argc, argv, ":hs:d:w:l:c:r:ftgo:O:", longopts, NULL)) != -1)
|
||||
switch (ch) {
|
||||
case 's':
|
||||
size = parse_num(ch, optarg, argv[0]);
|
||||
@ -127,82 +154,140 @@ int main(int argc, char* argv[]) {
|
||||
grow = 1;
|
||||
break;
|
||||
case 'o':
|
||||
outline = 1;
|
||||
outline = parse_num(ch, optarg, argv[0]);
|
||||
break;
|
||||
case 'O':
|
||||
strncpy(ocolor_name, optarg, sizeof(ocolor_name));
|
||||
break;
|
||||
case 'r':
|
||||
repeat = parse_num(ch, optarg, argv[0]);
|
||||
if (repeat == 0)
|
||||
repeat = -1;
|
||||
break;
|
||||
case ':':
|
||||
switch (optopt) {
|
||||
case 'o':
|
||||
outline = 2;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s: missing required argument for -%c\n\n", argv[0], optopt);
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case '?':
|
||||
fprintf(stderr, "%s: invalid option: -%c\n\n", argv[0], ch);
|
||||
// fallthrough
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
draw(argv[0],
|
||||
size, distance, wait, line_width, color_name,
|
||||
follow, transparent, grow, outline);
|
||||
}
|
||||
|
||||
void draw(
|
||||
char *name,
|
||||
int size, int distance, int wait, int line_width, char *color_name,
|
||||
int follow, int transparent, int grow, int outline
|
||||
) {
|
||||
// Setup display and such
|
||||
char *display_name = getenv("DISPLAY");
|
||||
if (!display_name) {
|
||||
fprintf(stderr, "%s: cannot connect to X server '%s'\n", name, display_name);
|
||||
fprintf(stderr, "%s: DISPLAY not set\n\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
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);
|
||||
if (!display) {
|
||||
fprintf(stderr, "%s: cannot open display '%s'\n\n", argv[0], display_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Get the mouse cursor position
|
||||
int win_x, win_y, root_x, root_y = 0;
|
||||
unsigned int mask = 0;
|
||||
Window child_win, root_win;
|
||||
XQueryPointer(display, XRootWindow(display, screen),
|
||||
&child_win, &root_win,
|
||||
&root_x, &root_y, &win_x, &win_y, &mask);
|
||||
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\n", argv[0], display_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Actually draw.
|
||||
do
|
||||
draw(argv[0], display, pointer_screen(argv[0], display),
|
||||
size, distance, wait, line_width, color_name,
|
||||
follow, transparent, grow, outline, ocolor_name);
|
||||
while (repeat == -1 || repeat--);
|
||||
|
||||
XCloseDisplay(display);
|
||||
}
|
||||
|
||||
// Identify which screen the cursor is on.
|
||||
int pointer_screen(char *name, Display *display) {
|
||||
int screencount = ScreenCount(display);
|
||||
|
||||
// The traditional case
|
||||
if (screencount == 1)
|
||||
return DefaultScreen(display);
|
||||
|
||||
// Multihead
|
||||
for (int s=0; s < screencount; s++) {
|
||||
Window root, win;
|
||||
int unused = 0;
|
||||
unsigned int unusedu = 0;
|
||||
Screen *screen = ScreenOfDisplay(display, s);
|
||||
|
||||
int found = XQueryPointer(display, RootWindowOfScreen(screen),
|
||||
&root, &win, &unused, &unused, &unused, &unused, &unusedu);
|
||||
if (found)
|
||||
return s;
|
||||
}
|
||||
|
||||
// Fall through (should never happen)
|
||||
fprintf(stderr, "%s: Unable to identify pointer screen, using Default\n", name);
|
||||
return DefaultScreen(display);
|
||||
}
|
||||
|
||||
// Try to get the centre of the cursor.
|
||||
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;
|
||||
XFree(c);
|
||||
}
|
||||
|
||||
void draw(char *name, Display *display, int screen,
|
||||
int size, int distance, int wait, int line_width, char *color_name,
|
||||
int follow, int transparent, int grow, int outline, char *ocolor_name
|
||||
) {
|
||||
// Get the mouse cursor position and size.
|
||||
int center_x, center_y;
|
||||
cursor_center(display, size, ¢er_x, ¢er_y);
|
||||
|
||||
// Create a window at the mouse position
|
||||
Window window;
|
||||
XSetWindowAttributes window_attr;
|
||||
window_attr.override_redirect = 1;
|
||||
|
||||
Colormap colormap = DefaultColormap(display, screen);
|
||||
if (transparent) {
|
||||
XVisualInfo vinfo;
|
||||
XMatchVisualInfo(display, DefaultScreen(display), 32, TrueColor, &vinfo);
|
||||
XMatchVisualInfo(display, screen, 32, TrueColor, &vinfo);
|
||||
window_attr.colormap = XCreateColormap(display, DefaultRootWindow(display), vinfo.visual, AllocNone);
|
||||
colormap = window_attr.colormap;
|
||||
window_attr.background_pixel = 0;
|
||||
window = XCreateWindow(display, XRootWindow(display, screen),
|
||||
root_x - size/2, root_y - size/2, // x, y position
|
||||
size, size, // width, height
|
||||
4, // border width
|
||||
vinfo.depth, // depth
|
||||
CopyFromParent, // class
|
||||
vinfo.visual, // visual
|
||||
center_x, // x position
|
||||
center_y, // y position
|
||||
size, size, // width, height
|
||||
4, // border width
|
||||
vinfo.depth, // depth
|
||||
CopyFromParent, // class
|
||||
vinfo.visual, // visual
|
||||
CWColormap | CWBorderPixel | CWBackPixel | CWOverrideRedirect, // valuemask
|
||||
&window_attr // attributes
|
||||
);
|
||||
&window_attr); // attributes
|
||||
}
|
||||
else {
|
||||
else
|
||||
window = XCreateWindow(display, XRootWindow(display, screen),
|
||||
root_x - size/2, root_y - size/2, // x, y position
|
||||
size, size, // width, height
|
||||
4, // border width
|
||||
DefaultDepth(display, screen), // depth
|
||||
CopyFromParent, // class
|
||||
DefaultVisual(display, screen), // visual
|
||||
CWOverrideRedirect, // valuemask
|
||||
&window_attr // attributes
|
||||
);
|
||||
}
|
||||
center_x, // x position
|
||||
center_y, // y position
|
||||
size, size, // width, height
|
||||
4, // border width
|
||||
DefaultDepth(display, screen), // depth
|
||||
CopyFromParent, // class
|
||||
DefaultVisual(display, screen), // visual
|
||||
CWOverrideRedirect, // valuemask
|
||||
&window_attr); // attributes
|
||||
|
||||
// Make round shaped window.
|
||||
XGCValues xgcv;
|
||||
@ -215,9 +300,10 @@ void draw(
|
||||
0, 0, // x, y position
|
||||
size, size, // Size
|
||||
0, 360 * 64); // Make it a full circle
|
||||
XFreeGC(display, part_shape);
|
||||
|
||||
XShapeCombineMask(display, window, ShapeBounding, 0,0, shape_mask, ShapeSet);
|
||||
XShapeCombineMask(display, window, ShapeClip, 0,0, shape_mask, ShapeSet);
|
||||
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.
|
||||
@ -264,20 +350,31 @@ void draw(
|
||||
unsigned long valuemask = 0;
|
||||
GC gc = XCreateGC(display, window, valuemask, &values);
|
||||
|
||||
Colormap colormap = DefaultColormap(display, screen);
|
||||
// Get colours.
|
||||
XColor color;
|
||||
XAllocNamedColor(display, colormap, color_name, &color, &color);
|
||||
int err = XAllocNamedColor(display, colormap, color_name, &color, &color);
|
||||
if (err == 0) {
|
||||
fprintf(stderr, "%s: invalid color value for -c/--color: '%s'\n\n", name, color_name);
|
||||
usage(name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
XColor color2;
|
||||
char color2_name[14]; // hash + 3x4-digit hex
|
||||
if (outline) {
|
||||
// Insert and convert to XColor.
|
||||
color2.red = 65535 - color.red;
|
||||
color2.green = 65535 - color.green;
|
||||
color2.blue = 65535 - color.blue;
|
||||
sprintf(color2_name,"#%04X%04X%04X", color2.red,color2.green, color2.blue);
|
||||
XAllocNamedColor(display, colormap, color2_name, &color2, &color2);
|
||||
} else {
|
||||
if (outline > 0) {
|
||||
if (ocolor_name[0] == 0) { // Use opposite colour.
|
||||
color2.red = 65535 - color.red;
|
||||
color2.green = 65535 - color.green;
|
||||
color2.blue = 65535 - color.blue;
|
||||
sprintf(ocolor_name, "#%04X%04X%04X", color2.red, color2.green, color2.blue);
|
||||
}
|
||||
int err = XAllocNamedColor(display, colormap, ocolor_name, &color2, &color2);
|
||||
if (err == 0) {
|
||||
fprintf(stderr, "%s: invalid color value for -O/--outline-color: '%s'\n\n", name, ocolor_name);
|
||||
usage(name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Set colour only once if not outline.
|
||||
XSetLineAttributes(display, gc, line_width, LineSolid, CapButt, JoinBevel);
|
||||
XSetForeground(display, gc, color.pixel);
|
||||
@ -285,19 +382,14 @@ void draw(
|
||||
|
||||
// Draw the circles
|
||||
int i = 1;
|
||||
for (i=1; i<=size; i+=distance) {
|
||||
if (follow) {
|
||||
for (i=1; i<=size; i+=distance) {
|
||||
if (follow)
|
||||
XClearWindow(display, window);
|
||||
}
|
||||
|
||||
int cs;
|
||||
if (grow)
|
||||
cs = i;
|
||||
else
|
||||
cs = size - i;
|
||||
int cs = grow ? i : size - i;
|
||||
|
||||
if (outline) {
|
||||
XSetLineAttributes(display, gc, line_width+2, LineSolid, CapButt, JoinBevel);
|
||||
if (outline > 0) {
|
||||
XSetLineAttributes(display, gc, line_width+outline, LineSolid, CapButt, JoinBevel);
|
||||
XSetForeground(display, gc, color2.pixel);
|
||||
XDrawArc(display, window, gc,
|
||||
size/2 - cs/2, size/2 - cs/2, // x, y position
|
||||
@ -315,10 +407,8 @@ void draw(
|
||||
0, 360 * 64); // Make it a full circle
|
||||
|
||||
if (follow) {
|
||||
XQueryPointer(display, XRootWindow(display, screen),
|
||||
&child_win, &root_win,
|
||||
&root_x, &root_y, &win_x, &win_y, &mask);
|
||||
XMoveWindow(display, window, root_x - size/2, root_y - size/2);
|
||||
cursor_center(display, size, ¢er_x, ¢er_y);
|
||||
XMoveWindow(display, window, center_x, center_y);
|
||||
}
|
||||
|
||||
XSync(display, False);
|
||||
@ -326,30 +416,28 @@ void draw(
|
||||
}
|
||||
|
||||
XFreeGC(display, gc);
|
||||
XCloseDisplay(display);
|
||||
XDestroyWindow(display, window);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
/* The MIT License (MIT)
|
||||
*
|
||||
* Copyright © 2015-2017 Martin Tournoij
|
||||
* Copyright © 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:
|
||||
* 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 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.
|
||||
*/
|
||||
* 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. */
|
||||
|
Loading…
Reference in New Issue
Block a user