summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am2
-rw-r--r--src/cheese-flash.c215
-rw-r--r--src/cheese-flash.h52
-rw-r--r--vapi/custom.vapi9
4 files changed, 278 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 31269f8..3fc3dfd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -59,6 +59,7 @@ contact-resources.c: contacts.gresource.xml app-menu.ui
--target=$@ --sourcedir=$(srcdir) --c-name contacts --generate-source
gnome_contacts_SOURCES = \
+ cheese-flash.c \
um-crop-area.c \
contact-resources.c \
gtk-notification.c \
@@ -78,6 +79,7 @@ CLEANFILES = \
*.vapi *.stamp
EXTRA_DIST = \
+ cheese-flash.h \
um-crop-area.h \
gtk-notification.h \
contacts.gresource.xml \
diff --git a/src/cheese-flash.c b/src/cheese-flash.c
new file mode 100644
index 0000000..131c9b3
--- /dev/null
+++ b/src/cheese-flash.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright © 2008 Alexander “weej” Jones <alex@weej.com>
+ * Copyright © 2008 Thomas Perl <thp@thpinfo.com>
+ * Copyright © 2009 daniel g. siegel <dgsiegel@gnome.org>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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 2 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/>.
+ */
+
+/* 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-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 */
+
+/* How long to hold the flash for */
+#define FLASH_DURATION 150
+
+/* The factor which defines how much the flash fades per frame */
+#define FLASH_FADE_FACTOR 0.95
+
+/* How many frames per second */
+#define FLASH_ANIMATION_RATE 120
+
+/* When to consider the flash finished so we can stop fading */
+#define FLASH_LOW_THRESHOLD 0.01
+
+G_DEFINE_TYPE (CheeseFlash, cheese_flash, G_TYPE_OBJECT);
+
+#define CHEESE_FLASH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CHEESE_TYPE_FLASH, CheeseFlashPrivate))
+
+typedef struct
+{
+ GtkWindow *window;
+ guint flash_timeout_tag;
+ guint fade_timeout_tag;
+} CheeseFlashPrivate;
+
+static gboolean
+cheese_flash_window_draw_event_cb (GtkWidget *widget, cairo_t *cr, gpointer user_data)
+{
+ cairo_fill (cr);
+ return TRUE;
+}
+
+static void
+cheese_flash_init (CheeseFlash *self)
+{
+ CheeseFlashPrivate *priv = CHEESE_FLASH_GET_PRIVATE (self);
+ cairo_region_t *input_region;
+ GtkWindow *window;
+ GdkScreen *screen;
+ GdkVisual *visual;
+
+ 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;
+}
+
+static void
+cheese_flash_dispose (GObject *object)
+{
+ CheeseFlashPrivate *priv = CHEESE_FLASH_GET_PRIVATE (object);
+
+ if (priv->window != NULL)
+ {
+ gtk_widget_destroy (GTK_WIDGET (priv->window));
+ priv->window = NULL;
+ }
+
+ if (G_OBJECT_CLASS (cheese_flash_parent_class)->dispose)
+ G_OBJECT_CLASS (cheese_flash_parent_class)->dispose (object);
+}
+
+static void
+cheese_flash_finalize (GObject *object)
+{
+ if (G_OBJECT_CLASS (cheese_flash_parent_class)->finalize)
+ G_OBJECT_CLASS (cheese_flash_parent_class)->finalize (object);
+}
+
+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->dispose = cheese_flash_dispose;
+ object_class->finalize = cheese_flash_finalize;
+}
+
+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);
+
+ /* exponentially decrease */
+ gtk_window_set_opacity (flash_window, opacity * FLASH_FADE_FACTOR);
+
+ if (opacity <= FLASH_LOW_THRESHOLD)
+ {
+ /* the flasher has finished when we reach the quit value */
+ gtk_widget_hide (GTK_WIDGET (flash_window));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+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;
+
+ /* 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;
+ }
+
+ 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;
+}
+
+void
+cheese_flash_fire (CheeseFlash *flash,
+ GdkRectangle *rect)
+{
+ CheeseFlashPrivate *flash_priv = CHEESE_FLASH_GET_PRIVATE (flash);
+ GtkWindow *flash_window = flash_priv->window;
+
+ 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);
+
+ gtk_window_set_opacity (flash_window, 0.99);
+ 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);
+}
+
+CheeseFlash *
+cheese_flash_new (void)
+{
+ return g_object_new (CHEESE_TYPE_FLASH, NULL);
+}
diff --git a/src/cheese-flash.h b/src/cheese-flash.h
new file mode 100644
index 0000000..6248aea
--- /dev/null
+++ b/src/cheese-flash.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright © 2008 Alexander “weej” Jones <alex@weej.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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 2 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 _CHEESE_FLASH_H_
+#define _CHEESE_FLASH_H_
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define CHEESE_TYPE_FLASH (cheese_flash_get_type ())
+#define CHEESE_FLASH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CHEESE_TYPE_FLASH, CheeseFlash))
+#define CHEESE_FLASH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CHEESE_TYPE_FLASH, CheeseFlashClass))
+#define CHEESE_IS_FLASH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CHEESE_TYPE_FLASH))
+#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
+{
+ GObjectClass parent_class;
+} CheeseFlashClass;
+
+typedef struct
+{
+ GObject parent_instance;
+} CheeseFlash;
+
+GType cheese_flash_get_type (void) G_GNUC_CONST;
+CheeseFlash *cheese_flash_new (void);
+
+void cheese_flash_fire (CheeseFlash *flash,
+ GdkRectangle *rect);
+
+G_END_DECLS
+
+#endif /* _CHEESE_FLASH_H_ */
diff --git a/vapi/custom.vapi b/vapi/custom.vapi
index c046977..d4372a3 100644
--- a/vapi/custom.vapi
+++ b/vapi/custom.vapi
@@ -69,3 +69,12 @@ namespace Um {
public Gdk.Pixbuf get_picture ();
}
}
+
+[CCode (cprefix = "Cheese", lower_case_cprefix = "cheese_", cheader_filename = "cheese-flash.h")]
+namespace Cheese {
+ public class Flash : Gtk.Window {
+ [CCode (has_construct_function = false, type = "CheeseFlash*")]
+ public Flash ();
+ public void fire (Gdk.Rectangle rect);
+ }
+}