I need to implement a visual bell for Konsole, because it doesn't honour the accessibility settings on my Ubuntu/KDE set-up.
I've cobbled together a utility to invert the currently focused X11 window, and have it triggered by Konsole, but I can't work out how to get it to re-invert the window without simply calling the invert program twice from a shell script (which works, but is ugly).
#include <X11/Xlib.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
Display *dpy;
Window focused=0;
Window rr;
int revert_to=0;
GC gc;
XGCValues gcv;
int xr, yr;
unsigned int wr, hr, bwr, dr;
struct timespec tp1;
struct timespec tp2;
dpy = XOpenDisplay(":0.0");
XGetInputFocus(dpy, &focused, &revert_to);
XGetGeometry(dpy, focused, &rr, &xr, &yr, &wr, &hr, &bwr, &dr);
gc = XCreateGC(dpy, focused, 0, NULL);
XSetSubwindowMode(dpy, gc, IncludeInferiors);
gcv.function = GXcopyInverted;
XChangeGC(dpy, gc, GCFunction, &gcv);
XFlushGC(dpy, gc);
XCopyArea(dpy, focused, focused, gc, xr, yr, wr, hr, 0, 0);
clock_gettime(CLOCK_REALTIME, &tp1);
for(;;) {
XEvent e;
while (XPending(dpy)) XNextEvent(dpy, &e);
usleep(5000);
clock_gettime(CLOCK_REALTIME, &tp2);
if (((tp2.tv_nsec - tp1.tv_nsec)/1000000 + 1000 * (tp2.tv_sec - tp1.tv_sec)) > 15)
break;
}
exit(0);
}
I tried to add a second copy operation - inverting or non-inverting - as follows:
int invert=0;
long slept=0;
for(;;) {
XEvent e;
while (XPending(dpy)) XNextEvent(dpy, &e);
if (invert == 0 || slept > 29) {
switch (invert++) {
case 1:
gcv.function = GXcopyInverted;
break;
case 2:
gcv.function = GXcopyInverted;
// gcv.function = GXcopy;
break;
case 3:
exit(0);
}
XChangeGC(dpy, gc, GCFunction, &gcv);
XFlushGC(dpy, gc);
XCopyArea(dpy, focused, focused, gc, xr, yr, wr, hr, 0, 0);
clock_gettime(CLOCK_REALTIME, &tp1);
slept=0;
}
usleep(5000);
clock_gettime(CLOCK_REALTIME, &tp2);
slept = ((tp2.tv_nsec - tp1.tv_nsec)/1000000 + 1000 * (tp2.tv_sec - tp1.tv_sec));
}
Sometimes it works, sometimes it just blanks the window, sometimes it doesn't do anything. The console refreshes the blanked or inverted data readily enough, but it's confusing.
I presume I have to return control to X11 somehow between inversion operations, to synchronise, but I don't really know what I'm doing. :)
The code I stole the basis of this from created a bitmap (to display in another window), so I suppose I could copy the original into a bitmap and then copy it back, but I'm enticed by the first listing above not needing that.
Help?