[gnome-flashback] screenshot: implement SelectArea method
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-flashback] screenshot: implement SelectArea method
- Date: Sun, 23 Aug 2015 08:12:46 +0000 (UTC)
commit b3891973ee235392af585e02e42e565f411349d1
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Sun Aug 23 10:52:52 2015 +0300
screenshot: implement SelectArea method
https://bugzilla.gnome.org/show_bug.cgi?id=753529
gnome-flashback/libscreenshot/Makefile.am | 2 +
.../libscreenshot/flashback-screenshot.c | 27 ++-
.../libscreenshot/flashback-select-area.c | 341 ++++++++++++++++++++
.../libscreenshot/flashback-select-area.h | 39 +++
4 files changed, 406 insertions(+), 3 deletions(-)
---
diff --git a/gnome-flashback/libscreenshot/Makefile.am b/gnome-flashback/libscreenshot/Makefile.am
index 1fa9bec..1d97423 100644
--- a/gnome-flashback/libscreenshot/Makefile.am
+++ b/gnome-flashback/libscreenshot/Makefile.am
@@ -16,6 +16,8 @@ libscreenshot_la_SOURCES = \
flashback-dbus-screenshot.h \
flashback-screenshot.c \
flashback-screenshot.h \
+ flashback-select-area.c \
+ flashback-select-area.h \
$(NULL)
libscreenshot_la_LDFLAGS = \
diff --git a/gnome-flashback/libscreenshot/flashback-screenshot.c
b/gnome-flashback/libscreenshot/flashback-screenshot.c
index 03e3471..20a2b15 100644
--- a/gnome-flashback/libscreenshot/flashback-screenshot.c
+++ b/gnome-flashback/libscreenshot/flashback-screenshot.c
@@ -21,6 +21,7 @@
#include "flashback-dbus-screenshot.h"
#include "flashback-screenshot.h"
+#include "flashback-select-area.h"
#define SCREENSHOT_DBUS_NAME "org.gnome.Shell.Screenshot"
#define SCREENSHOT_DBUS_PATH "/org/gnome/Shell/Screenshot"
@@ -104,9 +105,29 @@ handle_select_area (FlashbackDBusScreenshot *dbus_screenshot,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
- g_warning ("screenshot: select-area");
- flashback_dbus_screenshot_complete_select_area (dbus_screenshot, invocation,
- 0, 0, 0, 0);
+ FlashbackSelectArea *select_area;
+ gint x;
+ gint y;
+ gint width;
+ gint height;
+
+ select_area = flashback_select_area_new ();
+ x = y = width = height = 0;
+
+ if (flashback_select_area_select (select_area, &x, &y, &width, &height))
+ {
+ flashback_dbus_screenshot_complete_select_area (dbus_screenshot,
+ invocation,
+ x, y, width, height);
+ }
+ else
+ {
+ g_dbus_method_invocation_return_error (invocation, G_IO_ERROR,
+ G_IO_ERROR_CANCELLED,
+ "Operation was cancelled");
+ }
+
+ g_object_unref (select_area);
return TRUE;
}
diff --git a/gnome-flashback/libscreenshot/flashback-select-area.c
b/gnome-flashback/libscreenshot/flashback-select-area.c
new file mode 100644
index 0000000..dc7bb1e
--- /dev/null
+++ b/gnome-flashback/libscreenshot/flashback-select-area.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2015 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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-area-selection.c
+ * Copyright (C) 2001 - 2006 Jonathan Blandford, 2008 Cosimo Cecchi
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+
+#include "flashback-select-area.h"
+
+struct _FlashbackSelectArea
+{
+ GObject parent;
+
+ GtkWidget *window;
+ gboolean composited;
+
+ gboolean selecting;
+ gboolean selected;
+
+ gint x;
+ gint y;
+ gint width;
+ gint height;
+};
+
+G_DEFINE_TYPE (FlashbackSelectArea, flashback_select_area, G_TYPE_OBJECT)
+
+static gboolean
+draw_cb (GtkWidget *widget,
+ cairo_t *cr,
+ gpointer user_data)
+{
+ FlashbackSelectArea *select_area;
+ GtkStyleContext *context;
+ gint width;
+ gint height;
+
+ select_area = FLASHBACK_SELECT_AREA (user_data);
+
+ if (select_area->composited == FALSE)
+ return TRUE;
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_set_source_rgba (cr, 0, 0, 0, 0);
+ cairo_paint (cr);
+
+ context = gtk_widget_get_style_context (widget);
+ width = gtk_widget_get_allocated_width (widget);
+ height = gtk_widget_get_allocated_height (widget);
+
+ gtk_style_context_save (context);
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_RUBBERBAND);
+
+ gtk_render_background (context, cr, 0, 0, width, height);
+ gtk_render_frame (context, cr, 0, 0, width, height);
+
+ gtk_style_context_restore (context);
+
+ return TRUE;
+}
+
+static gboolean
+key_press_event_cb (GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer user_data)
+{
+ if (event->keyval == GDK_KEY_Escape)
+ gtk_main_quit ();
+
+ return TRUE;
+}
+
+static gboolean
+button_press_event_cb (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ FlashbackSelectArea *select_area;
+
+ select_area = FLASHBACK_SELECT_AREA (user_data);
+
+ if (select_area->selecting)
+ return TRUE;
+
+ select_area->selecting = TRUE;
+ select_area->x = event->x_root;
+ select_area->y = event->y_root;
+
+ return TRUE;
+}
+
+static gboolean
+button_release_event_cb (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ FlashbackSelectArea *select_area;
+
+ select_area = FLASHBACK_SELECT_AREA (user_data);
+
+ select_area->width = ABS (select_area->x - event->x_root);
+ select_area->height = ABS (select_area->y - event->y_root);
+ select_area->x = MIN (select_area->x, event->x_root);
+ select_area->y = MIN (select_area->y, event->y_root);
+
+ if (select_area->width != 0 && select_area->height != 0)
+ select_area->selected = TRUE;
+
+ gtk_main_quit ();
+
+ return TRUE;
+}
+
+static gboolean
+motion_notify_event_cb (GtkWidget *widget,
+ GdkEventMotion *event,
+ gpointer user_data)
+{
+ FlashbackSelectArea *select_area;
+ gint x;
+ gint y;
+ gint width;
+ gint height;
+ GtkWindow *window;
+
+ select_area = FLASHBACK_SELECT_AREA (user_data);
+
+ if (select_area->selecting == FALSE)
+ return TRUE;
+
+ x = MIN (select_area->x, event->x_root);
+ y = MIN (select_area->y, event->y_root);
+ width = ABS (select_area->x - event->x_root);
+ height = ABS (select_area->y - event->y_root);
+
+ window = GTK_WINDOW (select_area->window);
+
+ if (width <= 0 || height <= 0)
+ {
+ gtk_window_move (window, -100, -100);
+ gtk_window_resize (window, 10, 10);
+
+ return TRUE;
+ }
+
+ gtk_window_move (window, x, y);
+ gtk_window_resize (window, width, height);
+
+ if (select_area->composited == FALSE)
+ {
+ GdkWindow *gdk_window;
+
+ gdk_window = gtk_widget_get_window (select_area->window);
+
+ if (width > 2 && height > 2)
+ {
+ cairo_region_t *region;
+ cairo_rectangle_int_t rectangle;
+
+ rectangle.x = x;
+ rectangle.y = y;
+ rectangle.width = width;
+ rectangle.height = height;
+
+ region = cairo_region_create_rectangle (&rectangle);
+
+ rectangle.x++;
+ rectangle.y++;
+ rectangle.width -= 2;
+ rectangle.height -= 2;
+
+ cairo_region_subtract_rectangle (region, &rectangle);
+
+ gdk_window_shape_combine_region (gdk_window, region, 0, 0);
+ cairo_region_destroy (region);
+ }
+ else
+ {
+ gdk_window_shape_combine_region (gdk_window, NULL, 0, 0);
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+setup_window (FlashbackSelectArea *select_area)
+{
+ GdkScreen *screen;
+ GdkVisual *visual;
+ GtkWindow *window;
+
+ screen = gdk_screen_get_default ();
+ visual = gdk_screen_get_rgba_visual (screen);
+
+ if (gdk_screen_is_composited (screen) && visual != NULL)
+ {
+ gtk_widget_set_visual (select_area->window, visual);
+ select_area->composited = TRUE;
+ }
+
+ g_signal_connect (select_area->window, "draw",
+ G_CALLBACK (draw_cb), select_area);
+ g_signal_connect (select_area->window, "key-press-event",
+ G_CALLBACK (key_press_event_cb), select_area);
+ g_signal_connect (select_area->window, "button-press-event",
+ G_CALLBACK (button_press_event_cb), select_area);
+ g_signal_connect (select_area->window, "button-release-event",
+ G_CALLBACK (button_release_event_cb), select_area);
+ g_signal_connect (select_area->window, "motion-notify-event",
+ G_CALLBACK (motion_notify_event_cb), select_area);
+
+ window = GTK_WINDOW (select_area->window);
+
+ gtk_window_move (window, -100, -100);
+ gtk_window_resize (window, 10, 10);
+ gtk_widget_show (select_area->window);
+}
+
+static void
+flashback_select_area_dispose (GObject *object)
+{
+ FlashbackSelectArea *select_area;
+
+ select_area = FLASHBACK_SELECT_AREA (object);
+
+ if (select_area->window != NULL)
+ {
+ gtk_widget_destroy (select_area->window);
+ select_area->window = NULL;
+ }
+
+ G_OBJECT_CLASS (flashback_select_area_parent_class)->dispose (object);
+}
+
+static void
+flashback_select_area_class_init (FlashbackSelectAreaClass *select_area_class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (select_area_class);
+
+ object_class->dispose = flashback_select_area_dispose;
+}
+
+static void
+flashback_select_area_init (FlashbackSelectArea *select_area)
+{
+ select_area->window = gtk_window_new (GTK_WINDOW_POPUP);
+}
+
+FlashbackSelectArea *
+flashback_select_area_new (void)
+{
+ return g_object_new (FLASHBACK_TYPE_SELECT_AREA, NULL);
+}
+
+gboolean
+flashback_select_area_select (FlashbackSelectArea *select_area,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height)
+{
+ GdkDisplay *display;
+ GdkCursor *cursor;
+ GdkDeviceManager *manager;
+ GdkDevice *pointer;
+ GdkDevice *keyboard;
+ GdkWindow *window;
+ GdkGrabStatus status;
+
+ *x = *y = *width = *height = 0;
+
+ setup_window (select_area);
+
+ display = gdk_display_get_default ();
+ cursor = gdk_cursor_new_for_display (display, GDK_CROSSHAIR);
+ manager = gdk_display_get_device_manager (display);
+ pointer = gdk_device_manager_get_client_pointer (manager);
+ keyboard = gdk_device_get_associated_device (pointer);
+ window = gtk_widget_get_window (select_area->window);
+
+ status = gdk_device_grab (pointer, window, GDK_OWNERSHIP_NONE, FALSE,
+ GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK,
+ cursor, GDK_CURRENT_TIME);
+
+ if (status != GDK_GRAB_SUCCESS)
+ {
+ g_object_unref (cursor);
+ return FALSE;
+ }
+
+ if (gdk_display_device_is_grabbed (display, keyboard))
+ gdk_device_ungrab (keyboard, GDK_CURRENT_TIME);
+
+ status = gdk_device_grab (keyboard, window, GDK_OWNERSHIP_NONE, FALSE,
+ GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
+ NULL, GDK_CURRENT_TIME);
+
+ if (status != GDK_GRAB_SUCCESS)
+ {
+ gdk_device_ungrab (pointer, GDK_CURRENT_TIME);
+ g_object_unref (cursor);
+ return FALSE;
+ }
+
+ gtk_main ();
+
+ gdk_device_ungrab (pointer, GDK_CURRENT_TIME);
+ gdk_device_ungrab (keyboard, GDK_CURRENT_TIME);
+
+ if (select_area->selected == FALSE)
+ return FALSE;
+
+ *x = select_area->x;
+ *y = select_area->y;
+ *width = select_area->width;
+ *height = select_area->height;
+
+ return TRUE;
+}
diff --git a/gnome-flashback/libscreenshot/flashback-select-area.h
b/gnome-flashback/libscreenshot/flashback-select-area.h
new file mode 100644
index 0000000..40669a2
--- /dev/null
+++ b/gnome-flashback/libscreenshot/flashback-select-area.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2015 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef FLASHBACK_SELECT_AREA_H
+#define FLASHBACK_SELECT_AREA_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define FLASHBACK_TYPE_SELECT_AREA flashback_select_area_get_type ()
+G_DECLARE_FINAL_TYPE (FlashbackSelectArea, flashback_select_area,
+ FLASHBACK, SELECT_AREA, GObject)
+
+FlashbackSelectArea *flashback_select_area_new (void);
+
+gboolean flashback_select_area_select (FlashbackSelectArea *select_area,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height);
+
+G_END_DECLS
+
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]