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: |
12c34052e43ecca3f7c0b35b4d80d7bc |
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 3 * $ cc -Ofast safekill.c -lX11 -lc -osafekill 4 4 * © affero general public license 5 5 * a utility to make it harder to accidentally nuke 6 6 * important windows on i3wm or whatever. */ 7 7 8 8 #include <X11/Xlib.h> 9 9 #include <X11/Xutil.h> 10 +#include <X11/Xatom.h> 10 11 #include <stdio.h> 11 12 #include <stdlib.h> 12 13 #include <string.h> 13 14 #include <errno.h> 14 15 typedef enum { false, true } bool; 15 16 char* isvital(char* str) { 16 17 start: // tail calls for dipshits ................................................................................ 19 20 ++str; goto start; 20 21 } else { 21 22 if (str[1] == 'V' && str[2] == '}') 22 23 return str; 23 24 else { ++str; goto start; } 24 25 } 25 26 } 27 + 28 +Display *display; 29 + 30 +void killwin(Window w) { 31 + XEvent ev; 32 + long mask = SubstructureRedirectMask | SubstructureNotifyMask; 33 + ev.xclient.type = ClientMessage; 34 + ev.xclient.serial = 0; 35 + ev.xclient.send_event = True; 36 + ev.xclient.message_type = XInternAtom(display, "_NET_CLOSE_WINDOW", False); 37 + ev.xclient.window = w; 38 + ev.xclient.format = 32; 39 + 40 + if(!XSendEvent(display, DefaultRootWindow(display), False, mask, &ev)) { 41 + char* fallback = getenv("k_safekill_fallback"); 42 + bool nofb = (*fallback == '0' && fallback[1] == 0); 43 + 44 + fprintf(stderr,"\x1b[1mwarning:\x1b[m cannot send _NET_CLOSE_WINDOW event to root window; is your window manager okay?"); 45 + 46 + if (nofb) { 47 + fprintf(stderr,"\n"); 48 + } else { 49 + fprintf(stderr," falling back to XDestroyWindow, but this may wreck your shit - lots of multi-win apps do *not* like it.\n"); 50 + XDestroyWindow(display,w); 51 + } 52 + } 53 +} 26 54 int main(const int argc, const char** argv) { 27 - Display *display; 28 55 Window focus; 29 56 int revert; 30 57 31 58 bool active; 32 59 enum { vitalize, devitalize, hardkill, softkill } op; 33 60 34 61 if (argc > 3) goto usage; ................................................................................ 64 91 unsigned long temp = strtoul(argv[2], NULL, 0); 65 92 if (errno == EINVAL || errno == ERANGE) goto usage; 66 93 if (temp == 0) goto usage; 67 94 focus = (Window)temp; 68 95 } 69 96 70 97 if(op == hardkill) { 71 - XDestroyWindow(display,focus); 98 + killwin(focus); 72 99 XSync(display,false); 73 100 return 0; 74 101 } 75 102 76 103 XClassHint xclh; 77 104 if (XGetClassHint(display,focus,&xclh)) { 78 105 char* v; ................................................................................ 80 107 81 108 if (op == vitalize) return 0; // nothing need be done 82 109 else if (op == devitalize) { 83 110 strcpy(v, v+3); 84 111 XSetClassHint(display,focus,&xclh); 85 112 XSync(display,false); 86 113 } else if (op == softkill) { 87 - printf("softkill forbidden\n"); 114 + fprintf(stderr, "softkill forbidden\n"); 88 115 return 1; // ACCESS DENIED 89 116 } 90 117 } else { 91 118 if (op == vitalize) { 92 119 size_t sz=strlen(xclh.res_class); // TODO: remove double-walk 93 120 xclh.res_class=realloc(xclh.res_class, sz+4); 94 121 xclh.res_class[sz]='{'; ................................................................................ 96 123 xclh.res_class[sz+2]='}'; 97 124 xclh.res_class[sz+3]=0; 98 125 XSetClassHint(display,focus,&xclh); 99 126 XSync(display,false); 100 127 } else if (op == devitalize) return 0; 101 128 else if (op == softkill) { 102 129 // ice that motherfucker 103 - XDestroyWindow(display,focus); 130 + killwin(focus); 104 131 XSync(display,false); 105 132 return 3; 106 133 } 107 134 } 108 135 } else { 109 - printf("\x1b[1merror:\x1b[m bad window\n"); 136 + fprintf(stderr,"\x1b[1merror:\x1b[m bad window\n"); 110 137 goto usage; 111 138 } 112 139 113 140 return 0; 114 141 115 142 usage: 116 143 #define info "\x1b[34m-- " 117 144 #define param "\x1b[32m" 118 145 #define eol "\x1b[m\n" 119 146 #define bold "\x1b[1m" 120 147 #define nl " " 121 - printf(bold "usage:\x1b[0m %s " " " info "kill active window if non-vital" eol 148 + fprintf(stderr, bold "usage:\x1b[0m %s " " " info "kill active window if non-vital" eol 122 149 nl "%1$s -v " param "[id] " info "make [id] or active window vital" eol 123 150 nl "%1$s -c " param "[id] " info "clear vital flag on [id] or active window" eol 124 151 nl "%1$s -q " param "[id] " info "'emergency' kill w/o reference to vital flag" eol, 125 152 argv[0]); 126 153 return 1; 127 154 }