util  Check-in [12c34052e4]

Overview
Comment:make safekill use _NET_CLOSE_WINDOW extension where available instead of XDestroyWindow, which is super unfriendly and frequently crashes or hard-locks multi-window applications. XDestroyWindow is still available as a fallback if the extension fails; `export k_safekill_fallback=0` to stop this
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 12c34052e43ecca3f7c0b35b4d80d7bcdb3e46605334a309f9424e626109fe73
User & Date: lexi on 2019-04-12 00:49:13
Other Links: manifest | tags
Context
2019-04-13
11:22
add bgrd check-in: 011cb3726d user: lexi tags: trunk
2019-04-12
00:49
make safekill use _NET_CLOSE_WINDOW extension where available instead of XDestroyWindow, which is super unfriendly and frequently crashes or hard-locks multi-window applications. XDestroyWindow is still available as a fallback if the extension fails; `export k_safekill_fallback=0` to stop this check-in: 12c34052e4 user: lexi tags: trunk
2019-04-08
02:26
prettify header check-in: 8d306ffbd5 user: lexi tags: trunk
Changes

Modified safekill.c from [d7a13fcb31] to [54b90bee6d].

3
4
5
6
7
8
9

10
11
12
13
14
15
16
..
19
20
21
22
23
24
25
26

27


























28
29
30
31
32
33
34
..
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
..
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
..
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
 *  $ cc -Ofast safekill.c -lX11 -lc -osafekill
 *  © affero general public license
 * a utility to make it harder to accidentally nuke
 * important windows on i3wm or whatever. */

#include <X11/Xlib.h>
#include <X11/Xutil.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
typedef enum { false, true } bool;
char* isvital(char* str) {
	start: // tail calls for dipshits
................................................................................
			++str; goto start;
		} else {
			if (str[1] == 'V' && str[2] == '}')
				return str;
			else { ++str; goto start; }
		}
}
int main(const int argc, const char** argv) {

	Display *display;


























	Window focus;
	int revert;

	bool active;
	enum { vitalize, devitalize, hardkill, softkill } op;

	if (argc > 3) goto usage;
................................................................................
		unsigned long temp = strtoul(argv[2], NULL, 0);
		if (errno == EINVAL || errno == ERANGE) goto usage;
		if (temp == 0) goto usage;
		focus = (Window)temp;
	}

	if(op == hardkill) {
		XDestroyWindow(display,focus);
		XSync(display,false);
		return 0;
	}

	XClassHint xclh;
	if (XGetClassHint(display,focus,&xclh)) {
		char* v;
................................................................................

			if (op == vitalize) return 0; // nothing need be done
			else if (op == devitalize) {
				strcpy(v, v+3);
				XSetClassHint(display,focus,&xclh);
				XSync(display,false);
			} else if (op == softkill) {
				printf("softkill forbidden\n");
				return 1; // ACCESS DENIED
			}
		} else {
			if (op == vitalize) {
				size_t sz=strlen(xclh.res_class); // TODO: remove double-walk
				xclh.res_class=realloc(xclh.res_class, sz+4);
				xclh.res_class[sz]='{';
................................................................................
				xclh.res_class[sz+2]='}';
				xclh.res_class[sz+3]=0;
				XSetClassHint(display,focus,&xclh);
				XSync(display,false);
			} else if (op == devitalize) return 0;
			else if (op == softkill) {
				// ice that motherfucker
				XDestroyWindow(display,focus);
				XSync(display,false);
				return 3;
			}
		}
	} else {
		printf("\x1b[1merror:\x1b[m bad window\n");
		goto usage;
	}

	return 0;

usage:
	#define info  "\x1b[34m-- "
	#define param "\x1b[32m"
	#define eol   "\x1b[m\n"
	#define bold  "\x1b[1m"
	#define nl    "       "
	printf(bold "usage:\x1b[0m %s    "       "     " info "kill active window if non-vital" eol
						 nl "%1$s -v " param "[id] " info "make [id] or active window vital" eol
						 nl "%1$s -c " param "[id] " info "clear vital flag on [id] or active window" eol
						 nl "%1$s -q " param "[id] " info "'emergency' kill w/o reference to vital flag" eol,
				argv[0]);
	return 1;
}







>







 







<
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







|







 







|





|











|






3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
..
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
..
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
...
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
 *  $ cc -Ofast safekill.c -lX11 -lc -osafekill
 *  © affero general public license
 * a utility to make it harder to accidentally nuke
 * important windows on i3wm or whatever. */

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
typedef enum { false, true } bool;
char* isvital(char* str) {
	start: // tail calls for dipshits
................................................................................
			++str; goto start;
		} else {
			if (str[1] == 'V' && str[2] == '}')
				return str;
			else { ++str; goto start; }
		}
}


Display *display;

void killwin(Window w) {
	XEvent ev;
	long mask = SubstructureRedirectMask | SubstructureNotifyMask;
	ev.xclient.type       = ClientMessage;
	ev.xclient.serial     = 0;
	ev.xclient.send_event = True;
	ev.xclient.message_type = XInternAtom(display, "_NET_CLOSE_WINDOW", False);
	ev.xclient.window     = w;
	ev.xclient.format     = 32;
	
	if(!XSendEvent(display, DefaultRootWindow(display), False, mask, &ev)) {
		char* fallback = getenv("k_safekill_fallback");
		bool nofb = (*fallback == '0' && fallback[1] == 0);

		fprintf(stderr,"\x1b[1mwarning:\x1b[m cannot send _NET_CLOSE_WINDOW event to root window; is your window manager okay?");

		if (nofb) {
			fprintf(stderr,"\n");
		} else {
			fprintf(stderr," falling back to XDestroyWindow, but this may wreck your shit - lots of multi-win apps do *not* like it.\n");
			XDestroyWindow(display,w);
		}
	}
}
int main(const int argc, const char** argv) {
	Window focus;
	int revert;

	bool active;
	enum { vitalize, devitalize, hardkill, softkill } op;

	if (argc > 3) goto usage;
................................................................................
		unsigned long temp = strtoul(argv[2], NULL, 0);
		if (errno == EINVAL || errno == ERANGE) goto usage;
		if (temp == 0) goto usage;
		focus = (Window)temp;
	}

	if(op == hardkill) {
		killwin(focus);
		XSync(display,false);
		return 0;
	}

	XClassHint xclh;
	if (XGetClassHint(display,focus,&xclh)) {
		char* v;
................................................................................

			if (op == vitalize) return 0; // nothing need be done
			else if (op == devitalize) {
				strcpy(v, v+3);
				XSetClassHint(display,focus,&xclh);
				XSync(display,false);
			} else if (op == softkill) {
				fprintf(stderr, "softkill forbidden\n");
				return 1; // ACCESS DENIED
			}
		} else {
			if (op == vitalize) {
				size_t sz=strlen(xclh.res_class); // TODO: remove double-walk
				xclh.res_class=realloc(xclh.res_class, sz+4);
				xclh.res_class[sz]='{';
................................................................................
				xclh.res_class[sz+2]='}';
				xclh.res_class[sz+3]=0;
				XSetClassHint(display,focus,&xclh);
				XSync(display,false);
			} else if (op == devitalize) return 0;
			else if (op == softkill) {
				// ice that motherfucker
				killwin(focus);
				XSync(display,false);
				return 3;
			}
		}
	} else {
		fprintf(stderr,"\x1b[1merror:\x1b[m bad window\n");
		goto usage;
	}

	return 0;

usage:
	#define info  "\x1b[34m-- "
	#define param "\x1b[32m"
	#define eol   "\x1b[m\n"
	#define bold  "\x1b[1m"
	#define nl    "       "
	fprintf(stderr, bold "usage:\x1b[0m %s    "       "     " info "kill active window if non-vital" eol
						 nl "%1$s -v " param "[id] " info "make [id] or active window vital" eol
						 nl "%1$s -c " param "[id] " info "clear vital flag on [id] or active window" eol
						 nl "%1$s -q " param "[id] " info "'emergency' kill w/o reference to vital flag" eol,
				argv[0]);
	return 1;
}