iTranslated by AI
Making windows above the active window translucent in X
I recently started using Kubuntu and it's been pretty good, but I couldn't find a way to make only the windows above the active window semi-transparent.
You can make everything except the active window semi-transparent in the settings, though.

Actually, I've never seen that feature outside of Compiz, so maybe there's not much demand for it. It can't be helped, as people who use settings where the active window isn't automatically brought to the front are likely in the minority. It's a handy feature, though.
I asked ChatGPT and it seemed like I could control it from outside the window manager, so I decided to build it.
Potential Technical Elements
Specifying Window Opacity
Running the following command will change your mouse cursor to a ┼. If you click a window, that window's opacity will be set to 50%.
% xprop -f _NET_WM_WINDOW_OPACITY 32c -set _NET_WM_WINDOW_OPACITY 0x80000000
In C, it looks like this.
unsigned long opacity = 0x80000000;
XChangeProperty(display, window, XInternAtom(display, "_NET_WM_WINDOW_OPACITY", False), XA_CARDINAL, 32, PropModeReplace, &opacity, 1);
Getting the Window Stacking Order
% xwininfo -root -tree
This displays windows starting from the shallowest.
In C, using XQueryTree() returns a list of windows in order from deepest to shallowest.
Checking if Windows Overlap
Since xwininfo geometry provides the window position, width, and height, you can determine if they overlap through calculation.
However, the window selected with the ┼ in xwininfo is not sufficient; it seems you can't get the correct position on the display unless it's a window directly under the root.
The idea is to trace up the parents until the Parent window id in xwininfo -tree becomes the root window.
% xwininfo -tree -id 0x63ae7b | grep 'Parent window'
Parent window id: 0x137b273 (has no name)
% xwininfo -tree -id 0x137b273 | grep 'Parent window'
Parent window id: 0x137b272 (has no name)
% xwininfo -tree -id 0x137b272 | grep 'Parent window'
Parent window id: 0x5e3 (the root window) (has no name)
In this case, getting the geometry for 0x137b272 should work.
% xwininfo -id 0x137b272 | grep geometry
-geometry 582x438+2799+1344
In C, this can be obtained with XGetGeometry().
Window root;
int x, y;
unsigned int width, height, border_width, depth;
XGetGeometry(display, window, &root, &x, &y, &width, &height, &border_width, &depth);
Getting the Active Window
% xprop -root _NET_ACTIVE_WINDOW
_NET_ACTIVE_WINDOW(WINDOW): window id # 0x63ae7b
In C, it looks like this:
unsigned long type;
int format;
unsigned long nitems;
unsigned long bytes;
unsigned long *win;
XGetWindowProperty(display, window, XInternAtom(@display, '_NET_ACTIVE_WINDOW', False), 0, ~0, 0, AnyPropertyType, &type, &format, &nitems, &bytes, &win);
// win is the window ID
Detecting Active Window Changes
It seems you just need to monitor the _NET_ACTIVE_WINDOW event.
Running xprop -spy will notify you every time the active window changes.
% xprop -spy -root _NET_ACTIVE_WINDOW
_NET_ACTIVE_WINDOW(WINDOW): window id # 0x4a000b0
_NET_ACTIVE_WINDOW(WINDOW): window id # 0x4a000b0
_NET_ACTIVE_WINDOW(WINDOW): window id # 0x4c0002c
_NET_ACTIVE_WINDOW(WINDOW): window id # 0x4c0002c
_NET_ACTIVE_WINDOW(WINDOW): window id # 0x6000e0
_NET_ACTIVE_WINDOW(WINDOW): window id # 0x6000e0
_NET_ACTIVE_WINDOW(WINDOW): window id # 0x63ae7b
_NET_ACTIVE_WINDOW(WINDOW): window id # 0x63ae7b
^C
For some reason, it outputs two lines each time, but I don't know why.
In C, you can specify PropertyChangeMask with XSelectInput(), and calling XNextEvnet() will resume when a PropertyNotify event occurs.
Built it with Ruby
While writing it in C is a bit much and I could probably have done it with a shell script since commands exist, I like Ruby, so I built it in Ruby.
I looked for libraries to use X from Ruby but couldn't find a good one, so I started by creating wrappers for the necessary functions using Fiddle and then used those.
It's working reasonably well now, so I've released it as a Gem. You can install it with gem install wmadd. You can run it with wmadd.
Discussion