[gnome-contacts] Sync cheese-flash.[ch]



commit e404c5583b93fd0d5220d540922470e599936976
Author: Jonh Wendell <jonh wendell intel com>
Date:   Wed Jul 10 16:09:14 2013 -0300

    Sync cheese-flash.[ch]
    
    And properly modify callers to the new API.
    
    Old code was creating a window with the size of the screen. Thus,
    when taking a photo, the gnome-shell panel was then "hidden" by
    this big window. This has been fixed in "upstream" cheese, so, grab
    the latest code and make small modifications to fit the new API.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=702177

 src/cheese-flash.c              |  244 +++++++++++++++++++++++++++------------
 src/cheese-flash.h              |   35 ++++--
 src/contacts-avatar-dialog.vala |    6 +-
 vapi/custom.vapi                |    4 +-
 4 files changed, 200 insertions(+), 89 deletions(-)
---
diff --git a/src/cheese-flash.c b/src/cheese-flash.c
index 131c9b3..fd46818 100644
--- a/src/cheese-flash.c
+++ b/src/cheese-flash.c
@@ -19,46 +19,75 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-/* This is a "flash" object that you can create and invoke a method "flash" on to
- * flood the screen with white temporarily */
-
 #include <gtk/gtk.h>
 
+#include "cheese-camera.h"
 #include "cheese-flash.h"
 
-#ifdef GDK_WINDOWING_X11
-#include <X11/Xproto.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#include <gdk/gdkx.h>
-#endif /* GDK_WINDOWING_X11 */
+/**
+ * SECTION:cheese-flash
+ * @short_description: Flash the screen, like a real camera flash
+ * @stability: Unstable
+ * @include: cheese/cheese-flash.h
+ *
+ * #CheeseFlash is a window that you can create and invoke a method "flash" on
+ * to temporarily flood the screen with white.
+ */
+
+enum
+{
+  PROP_0,
+  PROP_PARENT,
+  PROP_LAST
+};
+
+static GParamSpec *properties[PROP_LAST];
 
-/* How long to hold the flash for */
-#define FLASH_DURATION 150
+/* How long to hold the flash for, in milliseconds. */
+static const guint FLASH_DURATION = 250;
 
 /* The factor which defines how much the flash fades per frame */
-#define FLASH_FADE_FACTOR 0.95
+static const gdouble FLASH_FADE_FACTOR = 0.95;
 
 /* How many frames per second */
-#define FLASH_ANIMATION_RATE 120
+static const guint FLASH_ANIMATION_RATE = 50;
 
 /* When to consider the flash finished so we can stop fading */
-#define FLASH_LOW_THRESHOLD 0.01
+static const gdouble FLASH_LOW_THRESHOLD = 0.01;
 
-G_DEFINE_TYPE (CheeseFlash, cheese_flash, G_TYPE_OBJECT);
+G_DEFINE_TYPE (CheeseFlash, cheese_flash, GTK_TYPE_WINDOW);
 
 #define CHEESE_FLASH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CHEESE_TYPE_FLASH, 
CheeseFlashPrivate))
 
-typedef struct
+/*
+ * CheeseFlashPrivate:
+ * @parent: the parent #GtkWidget, for choosing on which display to fire the
+ * flash
+ * @flash_timeout_tag: signal ID of the timeout to start fading in the flash
+ * @fade_timeout_tag: signal ID of the timeout to start fading out the flash
+ *
+ * Private data for #CheeseFlash.
+ */
+struct _CheeseFlashPrivate
 {
-  GtkWindow *window;
+  /*< private >*/
+  GtkWidget *parent;
   guint flash_timeout_tag;
   guint fade_timeout_tag;
-} CheeseFlashPrivate;
+};
 
+/*
+ * cheese_flash_draw_event_cb:
+ * @widget: the #CheeseFlash
+ * @cr: the Cairo context
+ * @user_data: the user data of the signal
+ *
+ * Draw the flash.
+ *
+ * Returns: %TRUE
+ */
 static gboolean
-cheese_flash_window_draw_event_cb (GtkWidget *widget, cairo_t *cr, gpointer user_data)
+cheese_flash_draw_event_cb (GtkWidget *widget, cairo_t *cr, gpointer user_data)
 {
   cairo_fill (cr);
   return TRUE;
@@ -67,57 +96,38 @@ cheese_flash_window_draw_event_cb (GtkWidget *widget, cairo_t *cr, gpointer user
 static void
 cheese_flash_init (CheeseFlash *self)
 {
-  CheeseFlashPrivate *priv = CHEESE_FLASH_GET_PRIVATE (self);
+  CheeseFlashPrivate *priv = self->priv = CHEESE_FLASH_GET_PRIVATE (self);
   cairo_region_t *input_region;
-  GtkWindow *window;
-  GdkScreen *screen;
-  GdkVisual *visual;
+  GtkWindow *window = GTK_WINDOW (self);
 
   priv->flash_timeout_tag = 0;
   priv->fade_timeout_tag  = 0;
 
-  window = GTK_WINDOW (gtk_window_new (GTK_WINDOW_POPUP));
-
   /* make it so it doesn't look like a window on the desktop (+fullscreen) */
   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);
 
   /* Don't take focus */
   gtk_window_set_accept_focus (window, FALSE);
   gtk_window_set_focus_on_map (window, FALSE);
 
-  /* no shadow */
-  screen = gtk_widget_get_screen (GTK_WIDGET (window));
-  visual = gdk_screen_get_rgba_visual (screen);
-  if (visual == NULL)
-    visual = gdk_screen_get_system_visual (screen);
-
-  gtk_widget_set_visual (GTK_WIDGET (window), visual);
-
   /* Don't consume input */
   gtk_widget_realize (GTK_WIDGET (window));
-
   input_region = cairo_region_create ();
   gdk_window_input_shape_combine_region (gtk_widget_get_window (GTK_WIDGET (window)), input_region, 0, 0);
   cairo_region_destroy (input_region);
 
-  g_signal_connect (G_OBJECT (window), "draw", G_CALLBACK (cheese_flash_window_draw_event_cb), NULL);
-  priv->window = window;
+  g_signal_connect (G_OBJECT (window), "draw", G_CALLBACK (cheese_flash_draw_event_cb), NULL);
 }
 
 static void
 cheese_flash_dispose (GObject *object)
 {
-  CheeseFlashPrivate *priv = CHEESE_FLASH_GET_PRIVATE (object);
+  CheeseFlashPrivate *priv = CHEESE_FLASH (object)->priv;
 
-  if (priv->window != NULL)
-  {
-    gtk_widget_destroy (GTK_WIDGET (priv->window));
-    priv->window = NULL;
-  }
+  g_clear_object (&priv->parent);
 
   if (G_OBJECT_CLASS (cheese_flash_parent_class)->dispose)
     G_OBJECT_CLASS (cheese_flash_parent_class)->dispose (object);
@@ -131,23 +141,71 @@ cheese_flash_finalize (GObject *object)
 }
 
 static void
+cheese_flash_set_property (GObject      *object,
+                           guint         prop_id,
+                           const GValue *value,
+                           GParamSpec   *pspec)
+{
+  CheeseFlashPrivate *priv = CHEESE_FLASH (object)->priv;
+
+  switch (prop_id)
+  {
+    case PROP_PARENT: {
+      GObject *object;
+      object = g_value_get_object (value);
+      if (object != NULL)
+        priv->parent = g_object_ref (object);
+      else
+        priv->parent = NULL;
+    }
+    break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
 cheese_flash_class_init (CheeseFlashClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
   g_type_class_add_private (klass, sizeof (CheeseFlashPrivate));
 
+  object_class->set_property = cheese_flash_set_property;
   object_class->dispose      = cheese_flash_dispose;
   object_class->finalize     = cheese_flash_finalize;
+
+  /**
+   * CheeseFlash:parent:
+   *
+   * Parent #GtkWidget for the #CheeseFlash. The flash will be fired on the
+   * screen where the parent widget is shown.
+   */
+  properties[PROP_PARENT] = g_param_spec_object ("parent",
+                                                 "Parent widget",
+                                                 "The flash will be fired on the screen where the parent 
widget is shown",
+                                                 GTK_TYPE_WIDGET,
+                                                 G_PARAM_WRITABLE |
+                                                 G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, PROP_LAST, properties);
 }
 
+/*
+ * cheese_flash_opacity_fade:
+ * @data: the #CheeseFlash
+ *
+ * Fade the flash out.
+ *
+ * Returns: %TRUE if the fade was completed, %FALSE if the flash must continue
+ * to fade
+ */
 static gboolean
 cheese_flash_opacity_fade (gpointer data)
 {
-  CheeseFlash        *flash        = data;
-  CheeseFlashPrivate *flash_priv   = CHEESE_FLASH_GET_PRIVATE (flash);
-  GtkWindow          *flash_window = flash_priv->window;
-  double              opacity      = gtk_window_get_opacity (flash_window);
+  GtkWindow *flash_window = GTK_WINDOW (data);
+  gdouble opacity = gtk_window_get_opacity (flash_window);
 
   /* exponentially decrease */
   gtk_window_set_opacity (flash_window, opacity * FLASH_FADE_FACTOR);
@@ -156,60 +214,98 @@ cheese_flash_opacity_fade (gpointer data)
   {
     /* the flasher has finished when we reach the quit value */
     gtk_widget_hide (GTK_WIDGET (flash_window));
-    return FALSE;
+    return G_SOURCE_REMOVE;
   }
 
-  return TRUE;
+  return G_SOURCE_CONTINUE;
 }
 
+/*
+ * cheese_flash_start_fade:
+ * @data: the #CheeseFlash
+ *
+ * Add a timeout to start the fade animation.
+ *
+ * Returns: %FALSE
+ */
 static gboolean
 cheese_flash_start_fade (gpointer data)
 {
-  CheeseFlash *self = data;
-  CheeseFlashPrivate *flash_priv = CHEESE_FLASH_GET_PRIVATE (self);
-  GtkWindow *flash_window = flash_priv->window;
+  CheeseFlashPrivate *flash_priv = CHEESE_FLASH (data)->priv;
+
+  GtkWindow *flash_window = GTK_WINDOW (data);
 
   /* If the screen is non-composited, just hide and finish up */
   if (!gdk_screen_is_composited (gtk_window_get_screen (flash_window)))
   {
     gtk_widget_hide (GTK_WIDGET (flash_window));
-    return FALSE;
+    return G_SOURCE_REMOVE;
   }
 
-  flash_priv->fade_timeout_tag = 
-    g_timeout_add_full (G_PRIORITY_DEFAULT,
-                        1000.0 / FLASH_ANIMATION_RATE,
-                        cheese_flash_opacity_fade,
-                        g_object_ref (self), g_object_unref);
-  return FALSE;
+  flash_priv->fade_timeout_tag = g_timeout_add (1000.0 / FLASH_ANIMATION_RATE, cheese_flash_opacity_fade, 
data);
+  return G_SOURCE_REMOVE;
 }
 
+/**
+ * cheese_flash_fire:
+ * @flash: a #CheeseFlash
+ *
+ * Fire the flash.
+ */
 void
-cheese_flash_fire (CheeseFlash  *flash,
-                   GdkRectangle *rect)
+cheese_flash_fire (CheeseFlash *flash)
 {
-  CheeseFlashPrivate *flash_priv = CHEESE_FLASH_GET_PRIVATE (flash);
-  GtkWindow *flash_window = flash_priv->window;
+  CheeseFlashPrivate *flash_priv;
+  GtkWidget          *parent;
+  GdkScreen          *screen;
+  GdkRectangle        rect, work_rect;
+  int                 monitor;
+  GtkWindow *flash_window;
+
+  g_return_if_fail (CHEESE_IS_FLASH (flash));
+
+  flash_priv = flash->priv;
+
+  g_return_if_fail (flash_priv->parent != NULL);
+
+  flash_window = GTK_WINDOW (flash);
 
   if (flash_priv->flash_timeout_tag > 0)
     g_source_remove (flash_priv->flash_timeout_tag);
   if (flash_priv->fade_timeout_tag > 0)
     g_source_remove (flash_priv->fade_timeout_tag);
 
-  gtk_window_resize (flash_window, rect->width, rect->height);
-  gtk_window_move (flash_window, rect->x, rect->y);
+  parent  = gtk_widget_get_toplevel (flash_priv->parent);
+  screen  = gtk_widget_get_screen (parent);
+  monitor = gdk_screen_get_monitor_at_window (screen,
+                                             gtk_widget_get_window (parent));
+
+  gdk_screen_get_monitor_geometry (screen, monitor, &rect);
+  gdk_screen_get_monitor_workarea (screen, monitor, &work_rect);
+  gdk_rectangle_intersect (&work_rect, &rect, &rect);
+
+  gtk_window_set_transient_for (GTK_WINDOW (flash_window), GTK_WINDOW (parent));
+  gtk_window_resize (flash_window, rect.width, rect.height);
+  gtk_window_move (flash_window, rect.x, rect.y);
 
-  gtk_window_set_opacity (flash_window, 0.99);
+  gtk_window_set_opacity (flash_window, 1);
   gtk_widget_show_all (GTK_WIDGET (flash_window));
-  flash_priv->flash_timeout_tag = 
-    g_timeout_add_full (G_PRIORITY_DEFAULT,
-                        FLASH_DURATION,
-                        cheese_flash_start_fade,
-                        g_object_ref (flash), g_object_unref);
+  flash_priv->flash_timeout_tag = g_timeout_add (FLASH_DURATION, cheese_flash_start_fade, (gpointer) flash);
 }
 
+/**
+ * cheese_flash_new:
+ * @parent: a parent #GtkWidget
+ *
+ * Create a new #CheeseFlash, associated with the @parent widget.
+ *
+ * Returns: a new #CheeseFlash
+ */
 CheeseFlash *
-cheese_flash_new (void)
+cheese_flash_new (GtkWidget *parent)
 {
-  return g_object_new (CHEESE_TYPE_FLASH, NULL);
+  return g_object_new (CHEESE_TYPE_FLASH,
+                       "parent", parent,
+                      "type", GTK_WINDOW_POPUP,
+                       NULL);
 }
diff --git a/src/cheese-flash.h b/src/cheese-flash.h
index 62db42f..4ce6d25 100644
--- a/src/cheese-flash.h
+++ b/src/cheese-flash.h
@@ -20,6 +20,7 @@
 #ifndef _CHEESE_FLASH_H_
 #define _CHEESE_FLASH_H_
 
+#include <gtk/gtk.h>
 #include <glib-object.h>
 
 G_BEGIN_DECLS
@@ -31,21 +32,37 @@ G_BEGIN_DECLS
 #define CHEESE_IS_FLASH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CHEESE_TYPE_FLASH))
 #define CHEESE_FLASH_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), CHEESE_TYPE_FLASH, CheeseFlashClass))
 
-typedef struct
+typedef struct _CheeseFlashPrivate CheeseFlashPrivate;
+typedef struct _CheeseFlashClass CheeseFlashClass;
+typedef struct _CheeseFlash CheeseFlash;
+
+/**
+ * CheeseFlashClass:
+ *
+ * Use the accessor functions below.
+ */
+struct _CheeseFlashClass
 {
-  GObjectClass parent_class;
-} CheeseFlashClass;
+  /*< private >*/
+  GtkWindowClass parent_class;
+};
 
-typedef struct
+/**
+ * CheeseFlash:
+ *
+ * Use the accessor functions below.
+ */
+struct _CheeseFlash
 {
-  GObject parent_instance;
-} CheeseFlash;
+  /*< private >*/
+  GtkWindow parent_instance;
+  CheeseFlashPrivate *priv;
+};
 
 GType        cheese_flash_get_type (void) G_GNUC_CONST;
-CheeseFlash *cheese_flash_new (void);
+CheeseFlash *cheese_flash_new (GtkWidget *parent);
 
-void cheese_flash_fire (CheeseFlash *flash,
-                        GdkRectangle *rect);
+void cheese_flash_fire (CheeseFlash *flash);
 
 #include <cheese/cheese-widget.h>
 
diff --git a/src/contacts-avatar-dialog.vala b/src/contacts-avatar-dialog.vala
index a246c3e..8c39e78 100644
--- a/src/contacts-avatar-dialog.vala
+++ b/src/contacts-avatar-dialog.vala
@@ -381,7 +381,7 @@ public class Contacts.AvatarDialog : Dialog {
     cheese.set_no_show_all (true);
     frame_grid.add (cheese);
 
-    flash = new Cheese.Flash ();
+    flash = new Cheese.Flash (this);
 
     toolbar = new Toolbar ();
     toolbar.get_style_context ().add_class (STYLE_CLASS_INLINE_TOOLBAR);
@@ -398,9 +398,7 @@ public class Contacts.AvatarDialog : Dialog {
     accept_button.clicked.connect ( (button) => {
        var camera = cheese.get_camera () as Cheese.Camera;
 
-       var screen = button.get_screen ();
-        Gdk.Rectangle rect = { 0, 0, screen.get_width (), screen.get_height ()};
-        flash.fire (rect);
+        flash.fire ();
 
        camera.photo_taken.connect ( (pix) => {
            set_crop_widget (pix);
diff --git a/vapi/custom.vapi b/vapi/custom.vapi
index 8313caa..d286d53 100644
--- a/vapi/custom.vapi
+++ b/vapi/custom.vapi
@@ -93,7 +93,7 @@ namespace Cheese {
        [CCode (cheader_filename = "cheese-flash.h")]
        public class Flash : Gtk.Window {
                [CCode (has_construct_function = false, type = "CheeseFlash*")]
-               public Flash ();
-               public void fire (Gdk.Rectangle rect);
+               public Flash (Gtk.Widget parent);
+               public void fire ();
        }
 }


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