diff options
| author | Victor Kareh <[email protected]> | 2026-05-20 21:41:47 -0400 |
|---|---|---|
| committer | Victor Kareh <[email protected]> | 2026-05-20 22:42:45 -0400 |
| commit | 71cf032ae5c002b428640c8d86fef8c0a15a5afd (patch) | |
| tree | 96a47a670083bdab00f4f7b643d2cb4c180ebed8 /mate-screenshot/src/screenshot-utils.c | |
| parent | 9f256dacee75beccdc8eaca219a111a9fea77e8d (diff) | |
| download | mate-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.c | 66 |
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; |
