From d3f56d9c0d98873a1dcafcd8c1983de9aac8c04b Mon Sep 17 00:00:00 2001 From: Ben Blain Date: Sun, 3 Jun 2018 11:27:51 +0100 Subject: Blank pixels outside monitor bounds (Bug #12177) For multiple monitor configurations, this sets the pixels outside the monitor geometries to black. diff --git a/lib/screenshooter-capture.c b/lib/screenshooter-capture.c index c610750..43cfa38 100644 --- a/lib/screenshooter-capture.c +++ b/lib/screenshooter-capture.c @@ -79,6 +79,12 @@ static GdkFilterReturn region_filter_func (GdkXEvent *xev GdkEvent *event, RbData *rbdata); static GdkPixbuf *get_rectangle_screenshot (gint delay); +static void mask_outside_monitor_bounds (GdkPixbuf *screenshot, + gint x_orig, + gint y_orig, + gint width, + gint height, + GdkWindow *root_window); static gboolean cb_key_pressed (GtkWidget *widget, GdkEventKey *event, RubberBandData *rbdata); @@ -350,6 +356,9 @@ static GdkPixbuf screenshot = gdk_pixbuf_get_from_window (root, x_orig, y_orig, width, height); + if (window == root) + mask_outside_monitor_bounds (screenshot, x_orig, y_orig, width, height, root); + /* Code adapted from gnome-screenshot: * Copyright (C) 2001-2006 Jonathan Blandford * Copyright (C) 2008 Cosimo Cecchi @@ -793,7 +802,91 @@ static GdkPixbuf else sleep (delay); - return gdk_pixbuf_get_from_window (root, x, y, w, h); + GdkPixbuf *screenshot = gdk_pixbuf_get_from_window (root, x, y, w, h); + mask_outside_monitor_bounds (screenshot, x, y, w, h, root); + return screenshot; +} + + + +static void mask_outside_monitor_bounds (GdkPixbuf *screenshot, + gint x_orig, + gint y_orig, + gint width, + gint height, + GdkWindow *root_window) +{ + GdkDisplay *display = gdk_window_get_display (root_window); + + gint monitor_count = gdk_display_get_n_monitors (display); + if (monitor_count < 2) + return; + + TRACE ("Blanking pixels outside monitor bounds"); + + cairo_rectangle_int_t rect; + cairo_region_t *region, *monitor_region; + gint i, n_rects; + + rect.x = x_orig; + rect.y = y_orig; + rect.width = width; + rect.height = height; + region = cairo_region_create_rectangle (&rect); + + for (i = 0; i < monitor_count; i++) + { + gdk_monitor_get_geometry (gdk_display_get_monitor (display, i), + &rect); + + /* Subtract each of the monitor geometries from the mask */ + monitor_region = cairo_region_create_rectangle (&rect); + cairo_region_subtract (region, monitor_region); + } + cairo_region_destroy (monitor_region); + + /* Region dimensions are relative to display, not image */ + cairo_region_translate (region, -x_orig, -y_orig); + + n_rects = cairo_region_num_rectangles (region); + + if (n_rects > 0) + { + guchar *pixels = gdk_pixbuf_get_pixels (screenshot); + gint rowstride = gdk_pixbuf_get_rowstride (screenshot); + gint n_channels = gdk_pixbuf_get_n_channels (screenshot); + gboolean has_alpha = gdk_pixbuf_get_has_alpha (screenshot); + + for (i = 0; i < n_rects; i++) + { + gint x, y, x2, y2; + guchar *row; + + cairo_region_get_rectangle (region, i, &rect); + + x2 = rect.x + rect.width; + y2 = rect.y + rect.height; + + for (y = rect.y; y < y2; y++) + { + guchar *p; + + row = pixels + y * rowstride; + p = row + rect.x * n_channels; + + for (x = rect.x; x < x2; x++) + { + *p++ = *p++ = *p++ = 0; + + if (has_alpha) + *p++ = 255; /* Opaque black */ + } + } + + } + } + + cairo_region_destroy (region); }