Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default to automatic ARGB use #27

Open
luebking opened this issue Apr 7, 2024 · 2 comments
Open

Default to automatic ARGB use #27

luebking opened this issue Apr 7, 2024 · 2 comments

Comments

@luebking
Copy link

luebking commented Apr 7, 2024

Preserves -t behavior, -t0 or -t1 to control the ARGB use and the default behavior just looks for a compositor and selects the proper mode. This even works when toggling the compositor while find-cursor is running.

diff --git a/find-cursor.c b/find-cursor.c
index 3931964..bbbeef6 100644
--- a/find-cursor.c
+++ b/find-cursor.c
@@ -21,6 +21,7 @@
 #include <X11/extensions/shape.h>
 
 void usage(char *name);
+int has_compositor(Display *dpy, int screen);
 int parse_num(int ch, char *opt, char *name);
 int pointer_screen(char *name, Display *display);
 void draw(char *name, Display *display, int screen,
@@ -35,7 +36,7 @@ static struct option longopts[] = {
 	{"line-width",    required_argument, NULL, 'l'},
 	{"color",         required_argument, NULL, 'c'},
 	{"follow",        no_argument,       NULL, 'f'},
-	{"transparent",   no_argument,       NULL, 't'},
+	{"transparent",   optional_argument, NULL, 't'}, // Optional for compat, as previously it was hard-coded to 1
 	{"grow",          no_argument,       NULL, 'g'},
 	{"outline",       optional_argument, NULL, 'o'}, // Optional for compat, as previously it was hard-coded to 2px.
 	{"repeat",        required_argument, NULL, 'r'},
@@ -62,10 +63,9 @@ void usage(char *name) {
 	"\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"
+	"  -t, --transparent   Make the window truly 'transparent'. [-1,0,1]\n"
+    "                      Defaults to -1 (auto) if unset, -t is equivalent to -t1\n"
+	"                      Use -t0 to explicitly disable it\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"
@@ -108,6 +108,13 @@ int parse_num(int ch, char *opt, char *name) {
 	return result;
 }
 
+int has_compositor(Display *dpy, int screen) {
+    char prop_name[20];
+    snprintf(prop_name, 20, "_NET_WM_CM_S%d", screen);
+    Atom prop_atom = XInternAtom(dpy, prop_name, False);
+    return XGetSelectionOwner(dpy, prop_atom) != None;
+}
+
 int main(int argc, char* argv[]) {
 	// Parse options
 	int size = 320;
@@ -117,14 +124,14 @@ int main(int argc, char* argv[]) {
 	char color_name[64] = "black";
 	char ocolor_name[64];
 	int follow = 0;
-	int transparent = 0;
+	int transparent = -1;
 	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:O:", longopts, NULL)) != -1)
+	while ((ch = getopt_long(argc, argv, ":hs:d:w:l:c:r:ft:go:O:", longopts, NULL)) != -1)
 		switch (ch) {
 		case 's':
 			size = parse_num(ch, optarg, argv[0]);
@@ -148,7 +155,7 @@ int main(int argc, char* argv[]) {
 			follow = 1;
 			break;
 		case 't':
-			transparent = 1;
+			transparent = parse_num(ch, optarg, argv[0]);
 			break;
 		case 'g':
 			grow = 1;
@@ -169,6 +176,9 @@ int main(int argc, char* argv[]) {
 			case 'o':
 				outline = 2;
 				break;
+            case 't':
+                transparent = 1;
+				break;
 			default:
 			    fprintf(stderr, "%s: missing required argument for -%c\n\n", argv[0], optopt);
 			    usage(argv[0]);
@@ -260,7 +270,7 @@ void draw(char *name, Display *display, int screen,
 	window_attr.override_redirect = 1;
 
     Colormap colormap = DefaultColormap(display, screen);
-	if (transparent) {
+	if (transparent > 0 || (transparent < 0 && has_compositor(display, screen))) {
 		XVisualInfo vinfo;
 		XMatchVisualInfo(display, screen, 32, TrueColor, &vinfo);
 		colormap = window_attr.colormap = XCreateColormap(display, DefaultRootWindow(display), vinfo.visual, AllocNone);
@arp242
Copy link
Owner

arp242 commented Apr 8, 2024

I think using --transparent {always,never,auto} would be nicer, maybe with some aliases for always and never (yes/no, on/off, true/false). I had to read your modified help text a few times to understand what it does.

Other than that, seems okay – just need to set the transparent variable from a string instead of a number.

@luebking
Copy link
Author

luebking commented Apr 8, 2024

I skipped the auto, it's implied by omission and makes the thing just more confusing by being pointed out.
(The objectives here are to maintain the behavior of "-t" while making the default "smart" but also allow to override that in either direction for debugging or corner cases, eg. unredirected windows)

diff --git a/find-cursor.c b/find-cursor.c
index 3931964..2caaf51 100644
--- a/find-cursor.c
+++ b/find-cursor.c
@@ -21,6 +21,7 @@
 #include <X11/extensions/shape.h>
 
 void usage(char *name);
+int has_compositor(Display *dpy, int screen);
 int parse_num(int ch, char *opt, char *name);
 int pointer_screen(char *name, Display *display);
 void draw(char *name, Display *display, int screen,
@@ -35,7 +36,7 @@ static struct option longopts[] = {
 	{"line-width",    required_argument, NULL, 'l'},
 	{"color",         required_argument, NULL, 'c'},
 	{"follow",        no_argument,       NULL, 'f'},
-	{"transparent",   no_argument,       NULL, 't'},
+	{"transparent",   optional_argument, NULL, 't'}, // Optional for compat, as previously it was hard-coded to 1
 	{"grow",          no_argument,       NULL, 'g'},
 	{"outline",       optional_argument, NULL, 'o'}, // Optional for compat, as previously it was hard-coded to 2px.
 	{"repeat",        required_argument, NULL, 'r'},
@@ -62,10 +63,9 @@ void usage(char *name) {
 	"\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"
+	"  -t, --transparent   Make the window truly 'transparent'. [yes|no]\n"
+	"                      If omitted the behavior is determined by the presence of a compositor.\n"
+	"                      If no parameter [yes|no] is given, \"yes\" is implied\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"
@@ -108,6 +108,39 @@ int parse_num(int ch, char *opt, char *name) {
 	return result;
 }
 
+int strtobool(int ch, char *opt, char *name) {
+	if (opt) {
+		switch (opt[0]) {
+		case 'a': case 'A': case 't': case 'T': case 'y': case 'Y': case '1':
+		case '-': // probably next parameter, so default to true
+			return 1;
+		case 'f': case 'F': case 'n': case 'N': case '0':
+			return 0;
+		case 'o': case 'O':
+			switch (opt[1]) {
+			case 'n': case 'N':
+				return 1;
+			case 'f': case 'F':
+				return 0;
+			default: // includes "\0"
+				break;
+			}
+		default:
+			break;
+		}
+		fprintf(stderr, "%s: value for -%c must be either true/false, on/off, yes/no, always/never or 0/1\n\n", name, ch);
+		exit(1);
+	}
+	return 1; // default to true
+}
+
+int has_compositor(Display *dpy, int screen) {
+	char prop_name[20];
+	snprintf(prop_name, 20, "_NET_WM_CM_S%d", screen);
+	Atom prop_atom = XInternAtom(dpy, prop_name, False);
+	return XGetSelectionOwner(dpy, prop_atom) != None;
+}
+
 int main(int argc, char* argv[]) {
 	// Parse options
 	int size = 320;
@@ -117,14 +150,14 @@ int main(int argc, char* argv[]) {
 	char color_name[64] = "black";
 	char ocolor_name[64];
 	int follow = 0;
-	int transparent = 0;
+	int transparent = -1;
 	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:O:", longopts, NULL)) != -1)
+	while ((ch = getopt_long(argc, argv, ":hs:d:w:l:c:r:ft::go:O:", longopts, NULL)) != -1)
 		switch (ch) {
 		case 's':
 			size = parse_num(ch, optarg, argv[0]);
@@ -148,7 +181,7 @@ int main(int argc, char* argv[]) {
 			follow = 1;
 			break;
 		case 't':
-			transparent = 1;
+			transparent = strtobool(ch, optarg, argv[0]);
 			break;
 		case 'g':
 			grow = 1;
@@ -169,6 +202,9 @@ int main(int argc, char* argv[]) {
 			case 'o':
 				outline = 2;
 				break;
+			case 't':
+				transparent = 1;
+				break;
 			default:
 			    fprintf(stderr, "%s: missing required argument for -%c\n\n", argv[0], optopt);
 			    usage(argv[0]);
@@ -260,7 +296,7 @@ void draw(char *name, Display *display, int screen,
 	window_attr.override_redirect = 1;
 
     Colormap colormap = DefaultColormap(display, screen);
-	if (transparent) {
+	if (transparent > 0 || (transparent < 0 && has_compositor(display, screen))) {
 		XVisualInfo vinfo;
 		XMatchVisualInfo(display, screen, 32, TrueColor, &vinfo);
 		colormap = window_attr.colormap = XCreateColormap(display, DefaultRootWindow(display), vinfo.visual, AllocNone);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants