[gnome-flashback] screenshot: finish screenshot implementation
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-flashback] screenshot: finish screenshot implementation
- Date: Thu, 10 Sep 2015 18:28:47 +0000 (UTC)
commit e159fd26f6276b824086470859bb1a4d550bb812
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Thu Sep 10 21:26:08 2015 +0300
screenshot: finish screenshot implementation
https://bugzilla.gnome.org/show_bug.cgi?id=753529
configure.ac | 2 +-
gnome-flashback/libscreenshot/gf-screenshot.c | 858 ++++++++++++++++++++++++-
2 files changed, 838 insertions(+), 22 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 92ce712..ba2a489 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,7 +79,7 @@ PKG_CHECK_MODULES(SCREENCAST, gtk+-3.0 >= $GTK_REQUIRED)
AC_SUBST(SCREENCAST_CFLAGS)
AC_SUBST(SCREENCAST_LIBS)
-PKG_CHECK_MODULES(SCREENSHOT, gtk+-3.0 >= $GTK_REQUIRED)
+PKG_CHECK_MODULES(SCREENSHOT, gtk+-3.0 >= $GTK_REQUIRED x11 xext)
AC_SUBST(SCREENSHOT_CFLAGS)
AC_SUBST(SCREENSHOT_LIBS)
diff --git a/gnome-flashback/libscreenshot/gf-screenshot.c b/gnome-flashback/libscreenshot/gf-screenshot.c
index 70940ca..25915af 100644
--- a/gnome-flashback/libscreenshot/gf-screenshot.c
+++ b/gnome-flashback/libscreenshot/gf-screenshot.c
@@ -13,11 +13,17 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Based on code in gnome-screenshot:
+ * https://git.gnome.org/browse/gnome-screenshot/tree/src/screenshot-utils.c
+ * Copyright (C) 2001 - 2006 Jonathan Blandford, 2008 Cosimo Cecchi
*/
#include "config.h"
#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <X11/extensions/shape.h>
#include "gf-dbus-screenshot.h"
#include "gf-flashspot.h"
@@ -27,18 +33,796 @@
#define SCREENSHOT_DBUS_NAME "org.gnome.Shell.Screenshot"
#define SCREENSHOT_DBUS_PATH "/org/gnome/Shell/Screenshot"
+typedef void (*GfInvocationCallback) (GfDBusScreenshot *dbus_screenshot,
+ GDBusMethodInvocation *invocation,
+ gboolean result,
+ const gchar *filename);
+
struct _GfScreenshot
{
GObject parent;
- gint bus_name;
GfDBusScreenshot *dbus_screenshot;
+ gint bus_name;
+
+ GHashTable *senders;
- GfFlashspot *flashspot;
+ GSettings *lockdown;
};
+typedef struct
+{
+ GfScreenshot *screenshot;
+ gchar *sender;
+} FlashspotData;
+
+typedef enum
+{
+ SCREENSHOT_SCREEN,
+ SCREENSHOT_WINDOW,
+ SCREENSHOT_AREA
+} ScreenshotType;
+
G_DEFINE_TYPE (GfScreenshot, gf_screenshot, G_TYPE_OBJECT)
+static gchar *
+get_unique_path (const gchar *path,
+ const gchar *filename)
+{
+ gchar *ptr;
+ gchar *real_filename;
+ gchar *real_path;
+ gint idx;
+
+ ptr = g_strrstr (filename, ".png");
+
+ if (ptr != NULL)
+ real_filename = g_strndup (filename, ptr - filename);
+ else
+ real_filename = g_strdup (filename);
+
+ real_path = NULL;
+ idx = 0;
+
+ do
+ {
+ gchar *name;
+
+ if (idx == 0)
+ name = g_strdup_printf ("%s.png", real_filename);
+ else
+ name = g_strdup_printf ("%s - %d.png", real_filename, idx);
+
+ g_free (real_path);
+ real_path = g_build_filename (path, name, NULL);
+ g_free (name);
+
+ idx++;
+ }
+ while (g_file_test (real_path, G_FILE_TEST_EXISTS));
+
+ g_free (real_filename);
+
+ return real_path;
+}
+
+static gchar *
+get_filename (const gchar *filename)
+{
+ const gchar *path;
+
+ if (g_path_is_absolute (filename))
+ return g_strdup (filename);
+
+ path = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES);
+
+ if (!g_file_test (path, G_FILE_TEST_EXISTS))
+ {
+ path = g_get_home_dir ();
+
+ if (!g_file_test (path, G_FILE_TEST_EXISTS))
+ return NULL;
+ }
+
+ return get_unique_path (path, filename);
+}
+
+static gboolean
+save_screenshot (GdkPixbuf *pixbuf,
+ const gchar *filename_in,
+ gchar **filename_out)
+{
+ gboolean result;
+ gchar *filename;
+ GError *error;
+
+ if (pixbuf == NULL)
+ return FALSE;
+
+ filename = get_filename (filename_in);
+
+ error = NULL;
+ result = gdk_pixbuf_save (pixbuf, filename, "png", &error, NULL);
+
+ if (result)
+ *filename_out = filename;
+ else
+ g_free (filename);
+
+ if (error != NULL)
+ {
+ g_warning ("Failed to save screenshot: %s", error->message);
+ g_error_free (error);
+ }
+
+ g_object_unref (pixbuf);
+
+ return result;
+}
+
+static void
+blank_rectangle_in_pixbuf (GdkPixbuf *pixbuf,
+ GdkRectangle *rect)
+{
+ gint x;
+ gint y;
+ gint x2;
+ gint y2;
+ guchar *pixels;
+ gint rowstride;
+ gint n_channels;
+ guchar *row;
+ gboolean has_alpha;
+
+ g_assert (gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
+
+ x2 = rect->x + rect->width;
+ y2 = rect->y + rect->height;
+
+ pixels = gdk_pixbuf_get_pixels (pixbuf);
+ rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+ has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
+ n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+
+ 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++ = 0;
+ *p++ = 0;
+ *p++ = 0;
+
+ if (has_alpha)
+ *p++ = 255;
+ }
+ }
+}
+
+static void
+blank_region_in_pixbuf (GdkPixbuf *pixbuf,
+ cairo_region_t *region)
+{
+ gint n_rects;
+ gint i;
+ gint width;
+ gint height;
+ cairo_rectangle_int_t pixbuf_rect;
+
+ n_rects = cairo_region_num_rectangles (region);
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+
+ pixbuf_rect.x = 0;
+ pixbuf_rect.y = 0;
+ pixbuf_rect.width = width;
+ pixbuf_rect.height = height;
+
+ for (i = 0; i < n_rects; i++)
+ {
+ cairo_rectangle_int_t rect;
+ cairo_rectangle_int_t dest;
+
+ cairo_region_get_rectangle (region, i, &rect);
+
+ if (gdk_rectangle_intersect (&rect, &pixbuf_rect, &dest))
+ blank_rectangle_in_pixbuf (pixbuf, &dest);
+ }
+}
+
+static cairo_region_t *
+make_region_with_monitors (GdkScreen *screen)
+{
+ cairo_region_t *region;
+ gint num_monitors;
+ gint i;
+
+ num_monitors = gdk_screen_get_n_monitors (screen);
+ region = cairo_region_create ();
+
+ for (i = 0; i < num_monitors; i++)
+ {
+ GdkRectangle rect;
+
+ gdk_screen_get_monitor_geometry (screen, i, &rect);
+ cairo_region_union_rectangle (region, &rect);
+ }
+
+ return region;
+}
+
+static void
+mask_monitors (GdkPixbuf *pixbuf,
+ GdkWindow *root_window)
+{
+ GdkScreen *screen;
+ cairo_region_t *region_with_monitors;
+ cairo_region_t *invisible_region;
+ cairo_rectangle_int_t rect;
+
+ screen = gdk_window_get_screen (root_window);
+ region_with_monitors = make_region_with_monitors (screen);
+
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = gdk_screen_get_width (screen);
+ rect.height = gdk_screen_get_height (screen);
+
+ invisible_region = cairo_region_create_rectangle (&rect);
+ cairo_region_subtract (invisible_region, region_with_monitors);
+
+ blank_region_in_pixbuf (pixbuf, invisible_region);
+
+ cairo_region_destroy (region_with_monitors);
+ cairo_region_destroy (invisible_region);
+}
+
+static Window
+find_wm_window (GdkDisplay *display,
+ GdkWindow *window)
+{
+ Display *xdisplay;
+ Window xid;
+ Window root;
+ Window parent;
+ Window *children;
+ unsigned int nchildren;
+
+ if (window == gdk_get_default_root_window ())
+ return None;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (display);
+ xid = GDK_WINDOW_XID (window);
+
+ while (TRUE)
+ {
+ if (XQueryTree (xdisplay, xid, &root, &parent, &children, &nchildren) == 0)
+ {
+ g_warning ("Couldn't find window manager window");
+ return None;
+ }
+
+ if (root == parent)
+ {
+ if (children != NULL)
+ XFree (children);
+
+ return xid;
+ }
+
+ xid = parent;
+
+ if (children != NULL)
+ XFree (children);
+ }
+}
+
+static void
+get_window_rect_coords (GdkWindow *window,
+ gboolean include_frame,
+ GdkRectangle *real_out,
+ GdkRectangle *screenshot_out)
+{
+ GdkRectangle real;
+ gint x;
+ gint y;
+ gint width;
+ gint height;
+ gint screen_width;
+ gint screen_height;
+
+ if (include_frame)
+ {
+ gdk_window_get_frame_extents (window, &real);
+ }
+ else
+ {
+ real.width = gdk_window_get_width (window);
+ real.height = gdk_window_get_height (window);
+
+ gdk_window_get_origin (window, &real.x, &real.y);
+ }
+
+ if (real_out != NULL)
+ *real_out = real;
+
+ x = real.x;
+ y = real.y;
+ width = real.width;
+ height = real.height;
+
+ if (x < 0)
+ {
+ width = width + x;
+ x = 0;
+ }
+
+ if (y < 0)
+ {
+ height = height + y;
+ y = 0;
+ }
+
+ screen_width = gdk_screen_width ();
+ if (x + width > screen_width)
+ width = screen_width - x;
+
+ screen_height = gdk_screen_height ();
+ if (y + height > screen_height)
+ height = screen_height - y;
+
+ if (screenshot_out != NULL)
+ {
+ screenshot_out->x = x;
+ screenshot_out->y = y;
+ screenshot_out->width = width;
+ screenshot_out->height = height;
+ }
+}
+
+static gboolean
+window_is_desktop (GdkWindow *window)
+{
+ GdkWindow *root_window;
+ GdkWindowTypeHint type_hint;
+
+ root_window = gdk_get_default_root_window ();
+
+ if (window == root_window)
+ return TRUE;
+
+ type_hint = gdk_window_get_type_hint (window);
+
+ if (type_hint == GDK_WINDOW_TYPE_HINT_DESKTOP)
+ return TRUE;
+
+ return FALSE;
+}
+
+static GdkWindow *
+find_active_window (void)
+{
+ GdkScreen *screen;
+
+ screen = gdk_screen_get_default ();
+
+ return gdk_screen_get_active_window (screen);
+}
+
+static GdkWindow *
+find_current_window (GdkDisplay *display)
+{
+ GdkWindow *window;
+
+ window = find_active_window ();
+
+ if (window == NULL)
+ {
+ GdkDeviceManager *manager;
+ GdkDevice *device;
+
+ manager = gdk_display_get_device_manager (display);
+ device = gdk_device_manager_get_client_pointer (manager);
+
+ window = gdk_device_get_window_at_position (device, NULL, NULL);
+ }
+
+ if (window)
+ {
+ if (window_is_desktop (window))
+ return NULL;
+
+ window = gdk_window_get_toplevel (window);
+ }
+
+ return window;
+}
+
+static GdkWindow *
+get_current_window (GdkDisplay *display,
+ ScreenshotType type)
+{
+ if (type == SCREENSHOT_WINDOW)
+ return find_current_window (display);
+
+ return gdk_get_default_root_window ();
+}
+
+static gboolean
+take_screenshot_real (GfScreenshot *screenshot,
+ ScreenshotType type,
+ gboolean include_frame,
+ gboolean include_cursor,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ const gchar *filename_in,
+ gchar **filename_out)
+{
+ GdkDisplay *display;
+ GdkWindow *window;
+ GdkRectangle real;
+ GdkRectangle s;
+ Window wm;
+ GdkWindow *wm_window;
+ GtkBorder frame_offset;
+ GdkWindow *root;
+ GdkPixbuf *pixbuf;
+
+ display = gdk_display_get_default ();
+ window = get_current_window (display, type);
+
+ if (window == NULL)
+ return FALSE;
+
+ get_window_rect_coords (window, include_frame, &real, &s);
+
+ wm = find_wm_window (display, window);
+
+ if (wm != None)
+ {
+ GdkRectangle wm_real;
+
+ wm_window = gdk_x11_window_foreign_new_for_display (display, wm);
+ get_window_rect_coords (wm_window, FALSE, &wm_real, NULL);
+
+ frame_offset.left = (gdouble) (real.x - wm_real.x);
+ frame_offset.top = (gdouble) (real.y - wm_real.y);
+ frame_offset.right = (gdouble) (wm_real.width - real.width - frame_offset.left);
+ frame_offset.bottom = (gdouble) (wm_real.height - real.height - frame_offset.top);
+ }
+ else
+ {
+ frame_offset.left = 0;
+ frame_offset.top = 0;
+ frame_offset.right = 0;
+ frame_offset.bottom = 0;
+ }
+
+ if (type != SCREENSHOT_WINDOW)
+ {
+ s.x = *x - s.x;
+ s.y = *y - s.y;
+ s.width = *width;
+ s.height = *height;
+ }
+
+ root = gdk_get_default_root_window ();
+ pixbuf = gdk_pixbuf_get_from_window (root, s.x, s.y, s.width, s.height);
+
+ if (type != SCREENSHOT_WINDOW && type != SCREENSHOT_AREA)
+ mask_monitors (pixbuf, root);
+
+ if (include_frame && wm != None)
+ {
+ XRectangle *rectangles;
+ GdkPixbuf *tmp;
+ gint rectangle_count;
+ gint rectangle_order;
+ gint i;
+
+ rectangles = XShapeGetRectangles (GDK_DISPLAY_XDISPLAY (display),
+ wm, ShapeBounding,
+ &rectangle_count, &rectangle_order);
+
+ if (rectangles && rectangle_count > 0)
+ {
+ gboolean has_alpha;
+
+ has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
+
+ tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, s.width, s.height);
+ gdk_pixbuf_fill (tmp, 0);
+
+ for (i = 0; i < rectangle_count; i++)
+ {
+ gint rec_x;
+ gint rec_y;
+ gint rec_width;
+ gint rec_height;
+ gint y2;
+
+ /* If we're using invisible borders, the ShapeBounding might not
+ * have the same size as the frame extents, as it would include
+ * the areas for the invisible borders themselves.
+ * In that case, trim every rectangle we get by the offset between
+ * the WM window size and the frame extents. */
+ rec_x = rectangles[i].x;
+ rec_y = rectangles[i].y;
+ rec_width = rectangles[i].width - (frame_offset.left + frame_offset.right);
+ rec_height = rectangles[i].height - (frame_offset.top + frame_offset.bottom);
+
+ if (real.x < 0)
+ {
+ rec_x += real.x;
+ rec_x = MAX(rec_x, 0);
+ rec_width += real.x;
+ }
+
+ if (real.y < 0)
+ {
+ rec_y += real.y;
+ rec_y = MAX(rec_y, 0);
+ rec_height += real.y;
+ }
+
+ if (s.x + rec_x + rec_width > gdk_screen_width ())
+ rec_width = gdk_screen_width () - s.x - rec_x;
+
+ if (s.y + rec_y + rec_height > gdk_screen_height ())
+ rec_height = gdk_screen_height () - s.y - rec_y;
+
+ for (y2 = rec_y; y2 < rec_y + rec_height; y2++)
+ {
+ guchar *src_pixels;
+ guchar *dest_pixels;
+ gint x2;
+
+ src_pixels = gdk_pixbuf_get_pixels (pixbuf)
+ + y2 * gdk_pixbuf_get_rowstride(pixbuf)
+ + rec_x * (has_alpha ? 4 : 3);
+ dest_pixels = gdk_pixbuf_get_pixels (tmp)
+ + y2 * gdk_pixbuf_get_rowstride (tmp)
+ + rec_x * 4;
+
+ for (x2 = 0; x2 < rec_width; x2++)
+ {
+ *dest_pixels++ = *src_pixels++;
+ *dest_pixels++ = *src_pixels++;
+ *dest_pixels++ = *src_pixels++;
+
+ if (has_alpha)
+ *dest_pixels++ = *src_pixels++;
+ else
+ *dest_pixels++ = 255;
+ }
+ }
+ }
+
+ g_object_unref (pixbuf);
+ pixbuf = tmp;
+
+ XFree (rectangles);
+ }
+ }
+
+ /* If we have a selected area, there were by definition no cursor in the
+ * screenshot. */
+ if (include_cursor && type == SCREENSHOT_AREA)
+ {
+ GdkCursor *cursor;
+ GdkPixbuf *cursor_pixbuf;
+
+ cursor = gdk_cursor_new_for_display (display, GDK_LEFT_PTR);
+ cursor_pixbuf = gdk_cursor_get_image (cursor);
+
+ if (cursor_pixbuf != NULL)
+ {
+ GdkDeviceManager *manager;
+ GdkDevice *device;
+ GdkRectangle rect;
+ gint cx;
+ gint cy;
+ gint xhot;
+ gint yhot;
+
+ manager = gdk_display_get_device_manager (display);
+ device = gdk_device_manager_get_client_pointer (manager);
+
+ if (wm_window != NULL)
+ gdk_window_get_device_position (wm_window, device, &cx, &cy, NULL);
+ else
+ gdk_window_get_device_position (window, device, &cx, &cy, NULL);
+
+ sscanf (gdk_pixbuf_get_option (cursor_pixbuf, "x_hot"), "%d", &xhot);
+ sscanf (gdk_pixbuf_get_option (cursor_pixbuf, "y_hot"), "%d", &yhot);
+
+ /* in rect we have the cursor window coordinates */
+ rect.x = cx + real.x;
+ rect.y = cy + real.y;
+ rect.width = gdk_pixbuf_get_width (cursor_pixbuf);
+ rect.height = gdk_pixbuf_get_height (cursor_pixbuf);
+
+ /* see if the pointer is inside the window */
+ if (gdk_rectangle_intersect (&real, &rect, &rect))
+ {
+ gint cursor_x;
+ gint cursor_y;
+
+ cursor_x = cx - xhot - frame_offset.left;
+ cursor_y = cy - yhot - frame_offset.top;
+
+ gdk_pixbuf_composite (cursor_pixbuf, pixbuf,
+ cursor_x, cursor_y,
+ rect.width, rect.height,
+ cursor_x, cursor_y,
+ 1.0, 1.0,
+ GDK_INTERP_BILINEAR,
+ 255);
+ }
+ }
+
+ g_clear_object (&cursor_pixbuf);
+ g_clear_object (&cursor);
+ }
+
+ if (type == SCREENSHOT_WINDOW)
+ {
+ GdkRectangle rect;
+
+ get_window_rect_coords (window, include_frame, NULL, &rect);
+
+ *x = rect.x;
+ *y = rect.y;
+ *width = rect.width;
+ *height = rect.height;
+ }
+
+ return save_screenshot (pixbuf, filename_in, filename_out);
+}
+
+static void
+remove_sender (GfScreenshot *screenshot,
+ const gchar *sender)
+{
+ gpointer name_id;
+
+ name_id = g_hash_table_lookup (screenshot->senders, sender);
+
+ if (name_id == NULL)
+ return;
+
+ g_bus_unwatch_name (GPOINTER_TO_UINT (name_id));
+ g_hash_table_remove (screenshot->senders, sender);
+}
+
+static FlashspotData *
+flashspot_data_new (GfScreenshot *screenshot,
+ const gchar *sender)
+{
+ FlashspotData *data;
+
+ data = (FlashspotData *) g_new0 (FlashspotData *, 1);
+
+ data->screenshot = g_object_ref (screenshot);
+ data->sender = g_strdup (sender);
+
+ return data;
+}
+
+static void
+flashspot_data_free (gpointer data)
+{
+ FlashspotData *real_data;
+
+ real_data = (FlashspotData *) data;
+
+ g_object_unref (real_data->screenshot);
+ g_free (real_data->sender);
+
+ g_free (real_data);
+}
+
+static void
+flashspot_finished (GfFlashspot *flashspot,
+ gpointer user_data)
+{
+ FlashspotData *data;
+
+ data = (FlashspotData *) g_object_get_data (G_OBJECT (flashspot), "data");
+
+ remove_sender (data->screenshot, data->sender);
+}
+
+static void
+name_vanished_handler (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ GfScreenshot *screenshot;
+
+ screenshot = GF_SCREENSHOT (user_data);
+
+ remove_sender (screenshot, name);
+}
+
+static void
+take_screenshot (GfScreenshot *screenshot,
+ GDBusMethodInvocation *invocation,
+ ScreenshotType type,
+ gboolean include_frame,
+ gboolean include_cursor,
+ gint x,
+ gint y,
+ gint width,
+ gint height,
+ GfInvocationCallback callback,
+ gboolean flash,
+ const gchar *filename_in)
+{
+ const gchar *sender;
+ gboolean disabled;
+ guint name_id;
+ gboolean result;
+ gchar *filename_out;
+
+ sender = g_dbus_method_invocation_get_sender (invocation);
+ disabled = g_settings_get_boolean (screenshot->lockdown, "disable-save-to-disk");
+
+ if (g_hash_table_lookup (screenshot->senders, sender) != NULL || disabled)
+ {
+ callback (screenshot->dbus_screenshot, invocation, FALSE, "");
+ return;
+ }
+
+ name_id = g_bus_watch_name (G_BUS_TYPE_SESSION, sender,
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ NULL, name_vanished_handler,
+ screenshot, NULL);
+
+ g_hash_table_insert (screenshot->senders, g_strdup (sender),
+ GUINT_TO_POINTER (name_id));
+
+ filename_out = NULL;
+ result = take_screenshot_real (screenshot, type,
+ include_frame, include_cursor,
+ &x, &y, &width, &height,
+ filename_in, &filename_out);
+
+ if (result && flash)
+ {
+ GfFlashspot *flashspot;
+ FlashspotData *data;
+
+ flashspot = gf_flashspot_new ();
+ data = flashspot_data_new (screenshot, sender);
+
+ g_object_set_data_full (G_OBJECT (flashspot), "data", data,
+ flashspot_data_free);
+
+ g_signal_connect (flashspot, "finished",
+ G_CALLBACK (flashspot_finished), NULL);
+
+ gf_flashspot_fire (flashspot, x, y, width, height);
+ g_object_unref (flashspot);
+ }
+ else
+ {
+ remove_sender (screenshot, sender);
+ }
+
+ callback (screenshot->dbus_screenshot, invocation,
+ result, filename_out ? filename_out : "");
+
+ g_free (filename_out);
+}
+
static void
scale_area (gint *x,
gint *y,
@@ -81,9 +865,20 @@ handle_screenshot (GfDBusScreenshot *dbus_screenshot,
const gchar *filename,
gpointer user_data)
{
- g_warning ("screenshot: screenshot");
- gf_dbus_screenshot_complete_screenshot (dbus_screenshot, invocation,
- FALSE, "");
+ GfScreenshot *screenshot;
+ GdkScreen *screen;
+ gint width;
+ gint height;
+
+ screenshot = GF_SCREENSHOT (user_data);
+ screen = gdk_screen_get_default ();
+ width = gdk_screen_get_width (screen);
+ height = gdk_screen_get_height (screen);
+
+ take_screenshot (screenshot, invocation, SCREENSHOT_SCREEN,
+ FALSE, include_cursor, 0, 0, width, height,
+ gf_dbus_screenshot_complete_screenshot,
+ flash, filename);
return TRUE;
}
@@ -97,9 +892,14 @@ handle_screenshot_window (GfDBusScreenshot *dbus_screenshot,
const gchar *filename,
gpointer user_data)
{
- g_warning ("screenshot: screenshot-window");
- gf_dbus_screenshot_complete_screenshot_window (dbus_screenshot, invocation,
- FALSE, "");
+ GfScreenshot *screenshot;
+
+ screenshot = GF_SCREENSHOT (user_data);
+
+ take_screenshot (screenshot, invocation, SCREENSHOT_WINDOW,
+ include_frame, include_cursor, 0, 0, 0, 0,
+ gf_dbus_screenshot_complete_screenshot_window,
+ flash, filename);
return TRUE;
}
@@ -115,6 +915,10 @@ handle_screenshot_area (GfDBusScreenshot *dbus_screenshot,
const gchar *filename,
gpointer user_data)
{
+ GfScreenshot *screenshot;
+
+ screenshot = GF_SCREENSHOT (user_data);
+
if (!check_area (x, y, width, height))
{
g_dbus_method_invocation_return_error (invocation, G_IO_ERROR,
@@ -125,10 +929,10 @@ handle_screenshot_area (GfDBusScreenshot *dbus_screenshot,
}
scale_area (&x, &y, &width, &height);
-
- g_warning ("screenshot: screenshot-area");
- gf_dbus_screenshot_complete_screenshot_area (dbus_screenshot, invocation,
- FALSE, "");
+ take_screenshot (screenshot, invocation, SCREENSHOT_AREA,
+ FALSE, FALSE, x, y, width, height,
+ gf_dbus_screenshot_complete_screenshot_area,
+ flash, filename);
return TRUE;
}
@@ -142,7 +946,7 @@ handle_flash_area (GfDBusScreenshot *dbus_screenshot,
gint height,
gpointer user_data)
{
- GfScreenshot *screenshot;
+ GfFlashspot *flashspot;
if (!check_area (x, y, width, height))
{
@@ -153,10 +957,11 @@ handle_flash_area (GfDBusScreenshot *dbus_screenshot,
return TRUE;
}
- screenshot = GF_SCREENSHOT (user_data);
-
scale_area (&x, &y, &width, &height);
- gf_flashspot_fire (screenshot->flashspot, x, y, width, height);
+
+ flashspot = gf_flashspot_new ();
+ gf_flashspot_fire (flashspot, x, y, width, height);
+ g_object_unref (flashspot);
gf_dbus_screenshot_complete_flash_area (dbus_screenshot, invocation);
@@ -243,6 +1048,12 @@ gf_screenshot_dispose (GObject *object)
screenshot = GF_SCREENSHOT (object);
+ if (screenshot->bus_name)
+ {
+ g_bus_unown_name (screenshot->bus_name);
+ screenshot->bus_name = 0;
+ }
+
if (screenshot->dbus_screenshot)
{
skeleton = G_DBUS_INTERFACE_SKELETON (screenshot->dbus_screenshot);
@@ -251,13 +1062,13 @@ gf_screenshot_dispose (GObject *object)
g_clear_object (&screenshot->dbus_screenshot);
}
- if (screenshot->bus_name)
+ if (screenshot->senders)
{
- g_bus_unown_name (screenshot->bus_name);
- screenshot->bus_name = 0;
+ g_hash_table_destroy (screenshot->senders);
+ screenshot->senders = NULL;
}
- g_clear_object (&screenshot->flashspot);
+ g_clear_object (&screenshot->lockdown);
G_OBJECT_CLASS (gf_screenshot_parent_class)->dispose (object);
}
@@ -276,13 +1087,18 @@ static void
gf_screenshot_init (GfScreenshot *screenshot)
{
screenshot->dbus_screenshot = gf_dbus_screenshot_skeleton_new ();
+
screenshot->bus_name = g_bus_own_name (G_BUS_TYPE_SESSION,
SCREENSHOT_DBUS_NAME,
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
G_BUS_NAME_OWNER_FLAGS_REPLACE,
(GBusAcquiredCallback) bus_acquired_handler,
NULL, NULL, screenshot, NULL);
- screenshot->flashspot = gf_flashspot_new ();
+
+ screenshot->senders = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ screenshot->lockdown = g_settings_new ("org.gnome.desktop.lockdown");
}
GfScreenshot *
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]