summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Kareh <[email protected]>2026-05-20 21:41:47 -0400
committerVictor Kareh <[email protected]>2026-05-27 16:04:15 -0400
commitd7b746d8faaeed50c6502c27d53fa7a895e2f2c9 (patch)
treee18ac660c610ca45580e4d305cb94c3aac76e5d1
parent9f256dacee75beccdc8eaca219a111a9fea77e8d (diff)
downloadmate-utils-d7b746d8faaeed50c6502c27d53fa7a895e2f2c9.tar.bz2
mate-utils-d7b746d8faaeed50c6502c27d53fa7a895e2f2c9.tar.xz
Fix window screenshot including invisible bordersHEADmaster
When marco resize borders are enabled, window screenshots had the entire frame window and included the invisible resize borders, causing artifacts around the window and leaking whatever was behind it. This reads the frame extents and compares with the client window position to determine the offset of the invisible borders and so we can adjust the dimensions to remove it. Fixes #236
-rw-r--r--mate-screenshot/src/screenshot-utils.c66
1 files changed, 64 insertions, 2 deletions
diff --git a/mate-screenshot/src/screenshot-utils.c b/mate-screenshot/src/screenshot-utils.c
index 6ee457c9..527c68c0 100644
--- a/mate-screenshot/src/screenshot-utils.c
+++ b/mate-screenshot/src/screenshot-utils.c
@@ -608,14 +608,18 @@ screenshot_get_pixbuf (GdkWindow *window,
gint x_real_orig, y_real_orig, x_orig, y_orig;
gint width, real_width, height, real_height;
gint screen_width, screen_height, scale;
+ gint invis_x = 0, invis_y = 0;
/* If the screenshot should include the border, we look for the WM window. */
+ Window client_xid = None;
+
if (include_border)
{
Window xid, wm;
xid = GDK_WINDOW_XID (window);
+ client_xid = xid;
wm = find_wm_window (xid);
if (wm != None)
@@ -640,6 +644,47 @@ screenshot_get_pixbuf (GdkWindow *window,
width = real_width;
height = real_height;
+ if (include_border && client_xid != None && width > 0 && height > 0)
+ {
+ Display *xdpy = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ Atom frame_extents = XInternAtom (xdpy, "_NET_FRAME_EXTENTS", False);
+ Atom type;
+ int fmt;
+ unsigned long nitems, bytes;
+ unsigned char *data = NULL;
+
+ if (XGetWindowProperty (xdpy, client_xid, 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, client_xid, &wa))
+ {
+ int vis_w = (int)(wa.width + ext[0] + ext[1]) / scale;
+ int vis_h = (int)(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 < real_width)
+ {
+ invis_x = (wa.x - (int) ext[0]);
+ x_orig += border_x;
+ width = vis_w;
+ }
+ if (border_y > 0 && vis_h < real_height)
+ {
+ invis_y = (wa.y - (int) ext[2]);
+ y_orig += border_y;
+ height = vis_h;
+ }
+ }
+ }
+ if (data)
+ XFree (data);
+ }
+
if (x_orig < 0)
{
width = width + x_orig;
@@ -711,11 +756,28 @@ screenshot_get_pixbuf (GdkWindow *window,
gint rec_width, rec_height;
gint y;
- rec_x = rectangles[i].x;
- rec_y = rectangles[i].y;
+ rec_x = rectangles[i].x - invis_x;
+ rec_y = rectangles[i].y - invis_y;
rec_width = rectangles[i].width / scale;
rec_height = rectangles[i].height / scale;
+ if (rec_x < 0)
+ {
+ rec_width += rec_x;
+ rec_x = 0;
+ }
+ if (rec_y < 0)
+ {
+ rec_height += rec_y;
+ rec_y = 0;
+ }
+ if (rec_x + rec_width > width)
+ rec_width = width - rec_x;
+ if (rec_y + rec_height > height)
+ rec_height = height - rec_y;
+ if (rec_width <= 0 || rec_height <= 0)
+ continue;
+
if (x_real_orig < 0)
{
rec_x += x_real_orig;