summaryrefslogtreecommitdiff
path: root/mate-screenshot/src/screenshot-utils.c
diff options
context:
space:
mode:
authorVictor Kareh <[email protected]>2026-05-20 21:41:47 -0400
committerVictor Kareh <[email protected]>2026-05-20 22:42:45 -0400
commit71cf032ae5c002b428640c8d86fef8c0a15a5afd (patch)
tree96a47a670083bdab00f4f7b643d2cb4c180ebed8 /mate-screenshot/src/screenshot-utils.c
parent9f256dacee75beccdc8eaca219a111a9fea77e8d (diff)
downloadmate-utils-fix-screenshot-invisible-border.tar.bz2
mate-utils-fix-screenshot-invisible-border.tar.xz
Fix window screenshot including invisible bordersfix-screenshot-invisible-border
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
Diffstat (limited to 'mate-screenshot/src/screenshot-utils.c')
-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..3ff15601 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]);
+ int vis_h = (int)(wa.height + ext[2] + ext[3]);
+ int border_x = wa.x - (int) ext[0];
+ int border_y = wa.y - (int) ext[2];
+
+ if (border_x > 0 && vis_w < real_width)
+ {
+ invis_x = border_x;
+ x_orig += border_x;
+ width = vis_w;
+ }
+ if (border_y > 0 && vis_h < real_height)
+ {
+ invis_y = border_y;
+ 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;