diff options
| author | Victor Kareh <[email protected]> | 2026-05-21 08:38:55 -0400 |
|---|---|---|
| committer | Victor Kareh <[email protected]> | 2026-05-27 16:05:24 -0400 |
| commit | 49dbc93a46badea10f35336627abd8014d8a7ea8 (patch) | |
| tree | 1dcc54b6ee0daa9c8df9320f7bff9e2cacd61996 | |
| parent | 414d0f6d92aba6dedbe9d2ee1f5e1e3a78e9d355 (diff) | |
| download | mate-panel-49dbc93a46badea10f35336627abd8014d8a7ea8.tar.bz2 mate-panel-49dbc93a46badea10f35336627abd8014d8a7ea8.tar.xz | |
window-list: show window decorations in preview thumbnails
Capture the window manager frame instead of the client window so that
preview thumbnails include title bars and borders. Use
_NET_FRAME_EXTENTS to strip invisible resize borders from the captured
frame.
| -rw-r--r-- | applets/wncklet/window-list.c | 63 |
1 files changed, 60 insertions, 3 deletions
diff --git a/applets/wncklet/window-list.c b/applets/wncklet/window-list.c index 17821cdd..cad33b17 100644 --- a/applets/wncklet/window-list.c +++ b/applets/wncklet/window-list.c @@ -21,6 +21,7 @@ #ifdef HAVE_X11 #include <gdk/gdkx.h> +#include <X11/Xatom.h> #define WNCK_I_KNOW_THIS_IS_UNSTABLE #include <libwnck/libwnck.h> #endif /* HAVE_X11 */ @@ -251,15 +252,32 @@ preview_window_thumbnail (WnckWindow *wnck_window, int *thumbnail_scale) { GdkWindow *window; - Window win; + GdkDisplay *display; + Display *xdpy; + Window win, frame, parent, root; + Window *children; + unsigned int nchildren; cairo_surface_t *thumbnail; cairo_t *cr; double ratio; int width, height, scale; + int src_x = 0, src_y = 0; win = wnck_window_get_xid (wnck_window); + display = gdk_display_get_default (); + xdpy = GDK_DISPLAY_XDISPLAY (display); - if ((window = gdk_x11_window_foreign_new_for_display (gdk_display_get_default (), win)) == NULL) + /* Find the frame window (WM parent) which includes decorations */ + frame = win; + if (XQueryTree (xdpy, win, &root, &parent, &children, &nchildren)) + { + if (children) + XFree (children); + if (parent != root) + frame = parent; + } + + if ((window = gdk_x11_window_foreign_new_for_display (display, frame)) == NULL) { return NULL; } @@ -268,6 +286,45 @@ preview_window_thumbnail (WnckWindow *wnck_window, width = gdk_window_get_width (window) * scale; height = gdk_window_get_height (window) * scale; + /* Strip invisible resize borders using _NET_FRAME_EXTENTS */ + if (frame != win) + { + Atom frame_extents = XInternAtom (xdpy, "_NET_FRAME_EXTENTS", False); + Atom type; + int fmt; + unsigned long nitems, bytes; + unsigned char *data = NULL; + + if (XGetWindowProperty (xdpy, win, frame_extents, 0, 4, False, + XA_CARDINAL, &type, &fmt, &nitems, &bytes, + &data) == Success && data && nitems >= 4) + { + unsigned long *ext = (unsigned long *) data; + XWindowAttributes wa; + + if (XGetWindowAttributes (xdpy, win, &wa)) + { + int vis_w = (wa.width + ext[0] + ext[1]) * scale; + int vis_h = (wa.height + ext[2] + ext[3]) * scale; + int border_x = (wa.x - (int) ext[0]) * scale; + int border_y = (wa.y - (int) ext[2]) * scale; + + if (border_x > 0 && vis_w < width) + { + src_x = border_x; + width = vis_w; + } + if (border_y > 0 && vis_h < height) + { + src_y = border_y; + height = vis_h; + } + } + } + if (data) + XFree (data); + } + /* Scale to configured size while maintaining aspect ratio */ if (width > height) { @@ -292,7 +349,7 @@ preview_window_thumbnail (WnckWindow *wnck_window, cairo_surface_set_device_scale (thumbnail, scale, scale); cr = cairo_create (thumbnail); cairo_scale (cr, ratio, ratio); - gdk_cairo_set_source_window (cr, window, 0, 0); + gdk_cairo_set_source_window (cr, window, -src_x / scale, -src_y / scale); cairo_paint (cr); cairo_destroy (cr); |
