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 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; } |