[gnome-flashback] screenshot: implement FlashArea method



commit 2c344cd347e23ecc8d4b87910ed268cb53f40f41
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Thu Sep 10 15:07:50 2015 +0300

    screenshot: implement FlashArea method
    
    https://bugzilla.gnome.org/show_bug.cgi?id=753529

 gnome-flashback/libscreenshot/Makefile.am     |    2 +
 gnome-flashback/libscreenshot/gf-flashspot.c  |  200 +++++++++++++++++++++++++
 gnome-flashback/libscreenshot/gf-flashspot.h  |   38 +++++
 gnome-flashback/libscreenshot/gf-screenshot.c |   69 +++++++++-
 4 files changed, 308 insertions(+), 1 deletions(-)
---
diff --git a/gnome-flashback/libscreenshot/Makefile.am b/gnome-flashback/libscreenshot/Makefile.am
index 38d1d20..2a8a024 100644
--- a/gnome-flashback/libscreenshot/Makefile.am
+++ b/gnome-flashback/libscreenshot/Makefile.am
@@ -12,6 +12,8 @@ libscreenshot_la_CFLAGS = \
        $(NULL)
 
 libscreenshot_la_SOURCES = \
+       gf-flashspot.c \
+       gf-flashspot.h \
        gf-screenshot.c \
        gf-screenshot.h \
        gf-select-area.c \
diff --git a/gnome-flashback/libscreenshot/gf-flashspot.c b/gnome-flashback/libscreenshot/gf-flashspot.c
new file mode 100644
index 0000000..ef29ba8
--- /dev/null
+++ b/gnome-flashback/libscreenshot/gf-flashspot.c
@@ -0,0 +1,200 @@
+/*
+ * 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/cheese-flash.c
+ * Copyright (C) 2008 Alexander “weej” Jones, 2008 Thomas Perl,
+ *               2009 daniel g. siegel
+ */
+
+#include "config.h"
+
+#include <gtk/gtk.h>
+
+#include "gf-flashspot.h"
+
+#define FLASH_DURATION 100
+#define FLASH_ANIMATION_RATE 200
+#define FLASH_FADE_FACTOR 0.95
+
+struct _GfFlashspot
+{
+  GObject    parent;
+
+  GtkWidget *window;
+
+  guint      flash_id;
+  guint      fade_id;
+};
+
+G_DEFINE_TYPE (GfFlashspot, gf_flashspot, G_TYPE_OBJECT)
+
+static gboolean
+fade (gpointer user_data)
+{
+  GfFlashspot *flashspot;
+  gdouble opacity;
+
+  flashspot = GF_FLASHSPOT (user_data);
+  opacity = gtk_widget_get_opacity (flashspot->window);
+
+  gtk_widget_set_opacity (flashspot->window, opacity * FLASH_FADE_FACTOR);
+
+  if (opacity <= 0.01)
+    {
+      gtk_widget_hide (flashspot->window);
+
+      flashspot->fade_id = 0;
+      return G_SOURCE_REMOVE;
+    }
+
+  return G_SOURCE_CONTINUE;
+}
+
+static gboolean
+start_fade (gpointer user_data)
+{
+  GfFlashspot *flashspot;
+  GdkScreen *screen;
+
+  flashspot = GF_FLASHSPOT (user_data);
+  screen = gtk_widget_get_screen (flashspot->window);
+
+  if (!gdk_screen_is_composited (screen))
+    {
+      gtk_widget_hide (flashspot->window);
+
+      flashspot->flash_id = 0;
+      return G_SOURCE_REMOVE;
+    }
+
+  flashspot->fade_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
+                                           1000.0 / FLASH_ANIMATION_RATE,
+                                           fade,
+                                           g_object_ref (flashspot),
+                                           g_object_unref);
+
+  flashspot->flash_id = 0;
+  return G_SOURCE_REMOVE;
+}
+
+static void
+gf_flashspot_dispose (GObject *object)
+{
+  GfFlashspot *flashspot;
+
+  flashspot = GF_FLASHSPOT (object);
+
+  if (flashspot->window != NULL)
+    {
+      gtk_widget_destroy (flashspot->window);
+      flashspot->window = NULL;
+    }
+
+  if (flashspot->flash_id > 0)
+    {
+      g_source_remove (flashspot->flash_id);
+      flashspot->flash_id = 0;
+    }
+
+  if (flashspot->fade_id > 0)
+    {
+      g_source_remove (flashspot->fade_id);
+      flashspot->fade_id = 0;
+    }
+
+  G_OBJECT_CLASS (gf_flashspot_parent_class)->dispose (object);
+}
+
+static void
+gf_flashspot_class_init (GfFlashspotClass *flashspot_class)
+{
+  GObjectClass *object_class;
+
+  object_class = G_OBJECT_CLASS (flashspot_class);
+
+  object_class->dispose = gf_flashspot_dispose;
+}
+
+static void
+gf_flashspot_init (GfFlashspot *flashspot)
+{
+  GtkWindow *window;
+  GdkScreen *screen;
+  GdkVisual *visual;
+  cairo_region_t *input_region;
+
+  flashspot->window = gtk_window_new (GTK_WINDOW_POPUP);
+
+  window = GTK_WINDOW (flashspot->window);
+  screen = gtk_widget_get_screen (flashspot->window);
+  visual = gdk_screen_get_rgba_visual (screen);
+
+  if (visual == NULL)
+    visual = gdk_screen_get_system_visual (screen);
+
+  gtk_window_set_decorated (window, FALSE);
+  gtk_window_set_skip_taskbar_hint (window, TRUE);
+  gtk_window_set_skip_pager_hint (window, TRUE);
+  gtk_window_set_keep_above (window, TRUE);
+  gtk_window_set_type_hint (window, GDK_WINDOW_TYPE_HINT_NOTIFICATION);
+  gtk_window_set_accept_focus (window, FALSE);
+  gtk_window_set_focus_on_map (window, FALSE);
+
+  gtk_widget_set_visual (flashspot->window, visual);
+  gtk_widget_realize (flashspot->window);
+
+  input_region = cairo_region_create ();
+  gdk_window_input_shape_combine_region (gtk_widget_get_window (flashspot->window),
+                                         input_region, 0, 0);
+  cairo_region_destroy (input_region);
+}
+
+GfFlashspot *
+gf_flashspot_new (void)
+{
+  return g_object_new (GF_TYPE_FLASHSPOT, NULL);
+}
+
+void
+gf_flashspot_fire (GfFlashspot *flashspot,
+                   gint         x,
+                   gint         y,
+                   gint         width,
+                   gint         height)
+{
+  GtkWindow *window;
+
+  if (flashspot->flash_id > 0)
+    g_source_remove (flashspot->flash_id);
+
+  if (flashspot->fade_id > 0)
+    g_source_remove (flashspot->fade_id);
+
+  window = GTK_WINDOW (flashspot->window);
+
+  gtk_window_move (window, x, y);
+  gtk_window_resize (window, width, height);
+
+  gtk_widget_set_opacity (flashspot->window, 0.99);
+  gtk_widget_show_all (flashspot->window);
+
+  flashspot->flash_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
+                                            FLASH_DURATION,
+                                            start_fade,
+                                            g_object_ref (flashspot),
+                                            g_object_unref);
+}
diff --git a/gnome-flashback/libscreenshot/gf-flashspot.h b/gnome-flashback/libscreenshot/gf-flashspot.h
new file mode 100644
index 0000000..47421ea
--- /dev/null
+++ b/gnome-flashback/libscreenshot/gf-flashspot.h
@@ -0,0 +1,38 @@
+/*
+ * 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 GF_FLASHSPOT_H
+#define GF_FLASHSPOT_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GF_TYPE_FLASHSPOT gf_flashspot_get_type ()
+G_DECLARE_FINAL_TYPE (GfFlashspot, gf_flashspot, GF, FLASHSPOT, GObject)
+
+GfFlashspot *gf_flashspot_new  (void);
+
+void         gf_flashspot_fire (GfFlashspot *flashspot,
+                                gint         x,
+                                gint         y,
+                                gint         width,
+                                gint         height);
+
+G_END_DECLS
+
+#endif
diff --git a/gnome-flashback/libscreenshot/gf-screenshot.c b/gnome-flashback/libscreenshot/gf-screenshot.c
index c4aad08..70940ca 100644
--- a/gnome-flashback/libscreenshot/gf-screenshot.c
+++ b/gnome-flashback/libscreenshot/gf-screenshot.c
@@ -20,6 +20,7 @@
 #include <gtk/gtk.h>
 
 #include "gf-dbus-screenshot.h"
+#include "gf-flashspot.h"
 #include "gf-screenshot.h"
 #include "gf-select-area.h"
 
@@ -32,10 +33,46 @@ struct _GfScreenshot
 
   gint              bus_name;
   GfDBusScreenshot *dbus_screenshot;
+
+  GfFlashspot      *flashspot;
 };
 
 G_DEFINE_TYPE (GfScreenshot, gf_screenshot, G_TYPE_OBJECT)
 
+static void
+scale_area (gint *x,
+            gint *y,
+            gint *width,
+            gint *height)
+{
+}
+
+static void
+unscale_area (gint *x,
+              gint *y,
+              gint *width,
+              gint *height)
+{
+}
+
+static gboolean
+check_area (gint x,
+            gint y,
+            gint width,
+            gint height)
+{
+  GdkScreen *screen;
+  gint screen_width;
+  gint screen_height;
+
+  screen = gdk_screen_get_default ();
+  screen_width = gdk_screen_get_width (screen);
+  screen_height = gdk_screen_get_height (screen);
+
+  return x >= 0 && y >= 0 && width > 0 && height > 0 &&
+         x + width <= screen_width && y + height <= screen_height;
+}
+
 static gboolean
 handle_screenshot (GfDBusScreenshot      *dbus_screenshot,
                    GDBusMethodInvocation *invocation,
@@ -78,6 +115,17 @@ handle_screenshot_area (GfDBusScreenshot      *dbus_screenshot,
                         const gchar           *filename,
                         gpointer               user_data)
 {
+  if (!check_area (x, y, width, height))
+    {
+      g_dbus_method_invocation_return_error (invocation, G_IO_ERROR,
+                                             G_IO_ERROR_CANCELLED,
+                                             "Invalid params");
+
+      return TRUE;
+    }
+
+  scale_area (&x, &y, &width, &height);
+
   g_warning ("screenshot: screenshot-area");
   gf_dbus_screenshot_complete_screenshot_area (dbus_screenshot, invocation,
                                                FALSE, "");
@@ -94,7 +142,22 @@ handle_flash_area (GfDBusScreenshot      *dbus_screenshot,
                    gint                   height,
                    gpointer               user_data)
 {
-  g_warning ("screenshot: flash-area");
+  GfScreenshot *screenshot;
+
+  if (!check_area (x, y, width, height))
+    {
+      g_dbus_method_invocation_return_error (invocation, G_IO_ERROR,
+                                             G_IO_ERROR_CANCELLED,
+                                             "Invalid params");
+
+      return TRUE;
+    }
+
+  screenshot = GF_SCREENSHOT (user_data);
+
+  scale_area (&x, &y, &width, &height);
+  gf_flashspot_fire (screenshot->flashspot, x, y, width, height);
+
   gf_dbus_screenshot_complete_flash_area (dbus_screenshot, invocation);
 
   return TRUE;
@@ -116,6 +179,7 @@ handle_select_area (GfDBusScreenshot      *dbus_screenshot,
 
   if (gf_select_area_select (select_area, &x, &y, &width, &height))
     {
+      unscale_area (&x, &y, &width, &height);
       gf_dbus_screenshot_complete_select_area (dbus_screenshot, invocation,
                                                x, y, width, height);
     }
@@ -193,6 +257,8 @@ gf_screenshot_dispose (GObject *object)
       screenshot->bus_name = 0;
     }
 
+  g_clear_object (&screenshot->flashspot);
+
   G_OBJECT_CLASS (gf_screenshot_parent_class)->dispose (object);
 }
 
@@ -216,6 +282,7 @@ gf_screenshot_init (GfScreenshot *screenshot)
                                          G_BUS_NAME_OWNER_FLAGS_REPLACE,
                                          (GBusAcquiredCallback) bus_acquired_handler,
                                          NULL, NULL, screenshot, NULL);
+  screenshot->flashspot = gf_flashspot_new ();
 }
 
 GfScreenshot *


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]