2
* Copyright © 2008 Alexander “weej” Jones <alex@weej.com>
3
* Copyright © 2008 Thomas Perl <thp@thpinfo.com>
4
* Copyright © 2009 daniel g. siegel <dgsiegel@gnome.org>
6
* Licensed under the GNU General Public License Version 2
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program. If not, see <http://www.gnu.org/licenses/>.
22
/* This is a "flash" object that you can create and invoke a method "flash" on to
23
* flood the screen with white temporarily */
27
#include <cheese-camera.h>
28
#include "cheese-flash.h"
36
/* How long to hold the flash for */
37
#define FLASH_DURATION 250
39
/* The factor which defines how much the flash fades per frame */
40
#define FLASH_FADE_FACTOR 0.95
42
/* How many frames per second */
43
#define FLASH_ANIMATION_RATE 50
45
/* When to consider the flash finished so we can stop fading */
46
#define FLASH_LOW_THRESHOLD 0.01
48
G_DEFINE_TYPE (CheeseFlash, cheese_flash, G_TYPE_OBJECT);
50
#define CHEESE_FLASH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CHEESE_TYPE_FLASH, CheeseFlashPrivate))
56
guint flash_timeout_tag;
57
guint fade_timeout_tag;
61
cheese_flash_window_expose_event_cb (GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
65
cr = gdk_cairo_create (gtk_widget_get_window (widget));
66
cairo_set_source_rgb (cr, 1, 1, 1);
67
cairo_rectangle (cr, event->area.x, event->area.y, event->area.width, event->area.height);
75
cheese_flash_init (CheeseFlash *self)
77
CheeseFlashPrivate *priv = CHEESE_FLASH_GET_PRIVATE (self);
81
priv->flash_timeout_tag = 0;
82
priv->fade_timeout_tag = 0;
84
window = GTK_WINDOW (gtk_window_new (GTK_WINDOW_POPUP));
86
/* make it so it doesn't look like a window on the desktop (+fullscreen) */
87
gtk_window_set_decorated (window, FALSE);
88
gtk_window_set_skip_taskbar_hint (window, TRUE);
89
gtk_window_set_skip_pager_hint (window, TRUE);
90
gtk_window_set_keep_above (window, TRUE);
92
/* Don't take focus */
93
gtk_window_set_accept_focus (window, FALSE);
94
gtk_window_set_focus_on_map (window, FALSE);
96
/* Don't consume input */
97
gtk_widget_realize (GTK_WIDGET (window));
98
GdkRegion *input_region;
99
input_region = gdk_region_new ();
100
gdk_window_input_shape_combine_region (gtk_widget_get_window (GTK_WIDGET (window)), input_region, 0, 0);
101
gdk_region_destroy (input_region);
103
g_signal_connect (G_OBJECT (window), "expose-event", G_CALLBACK (cheese_flash_window_expose_event_cb), NULL);
104
priv->window = window;
108
cheese_flash_dispose (GObject *object)
110
CheeseFlashPrivate *priv = CHEESE_FLASH_GET_PRIVATE (object);
112
if (priv->window != NULL)
114
gtk_widget_destroy (GTK_WIDGET (priv->window));
117
if (priv->parent != NULL)
119
g_object_unref (priv->parent);
123
if (G_OBJECT_CLASS (cheese_flash_parent_class)->dispose)
124
G_OBJECT_CLASS (cheese_flash_parent_class)->dispose (object);
128
cheese_flash_finalize (GObject *object)
130
if (G_OBJECT_CLASS (cheese_flash_parent_class)->finalize)
131
G_OBJECT_CLASS (cheese_flash_parent_class)->finalize (object);
135
cheese_flash_set_property (GObject *object,
140
CheeseFlashPrivate *priv = CHEESE_FLASH_GET_PRIVATE (object);
146
object = g_value_get_object (value);
148
priv->parent = g_object_ref (object);
154
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
160
cheese_flash_class_init (CheeseFlashClass *klass)
162
GObjectClass *object_class = G_OBJECT_CLASS (klass);
164
g_type_class_add_private (klass, sizeof (CheeseFlashPrivate));
166
object_class->set_property = cheese_flash_set_property;
167
object_class->dispose = cheese_flash_dispose;
168
object_class->finalize = cheese_flash_finalize;
170
g_object_class_install_property (object_class, PROP_PARENT,
171
g_param_spec_object ("parent",
179
cheese_flash_opacity_fade (gpointer data)
181
CheeseFlash *flash = data;
182
CheeseFlashPrivate *flash_priv = CHEESE_FLASH_GET_PRIVATE (flash);
183
GtkWindow *flash_window = flash_priv->window;
184
double opacity = gtk_window_get_opacity (flash_window);
186
/* exponentially decrease */
187
gtk_window_set_opacity (flash_window, opacity * FLASH_FADE_FACTOR);
189
if (opacity <= FLASH_LOW_THRESHOLD)
191
/* the flasher has finished when we reach the quit value */
192
gtk_widget_hide (GTK_WIDGET (flash_window));
200
cheese_flash_start_fade (gpointer data)
202
CheeseFlashPrivate *flash_priv = CHEESE_FLASH_GET_PRIVATE (CHEESE_FLASH (data));
204
GtkWindow *flash_window = flash_priv->window;
206
/* If the screen is non-composited, just hide and finish up */
207
if (!gdk_screen_is_composited (gtk_window_get_screen (flash_window)))
209
gtk_widget_hide (GTK_WIDGET (flash_window));
213
flash_priv->fade_timeout_tag = g_timeout_add (1000.0 / FLASH_ANIMATION_RATE, cheese_flash_opacity_fade, data);
218
cheese_flash_fire (CheeseFlash *flash)
220
CheeseFlashPrivate *flash_priv = CHEESE_FLASH_GET_PRIVATE (flash);
226
g_return_if_fail (flash_priv->parent != NULL);
228
GtkWindow *flash_window = flash_priv->window;
230
if (flash_priv->flash_timeout_tag > 0)
231
g_source_remove (flash_priv->flash_timeout_tag);
232
if (flash_priv->fade_timeout_tag > 0)
233
g_source_remove (flash_priv->fade_timeout_tag);
235
parent = gtk_widget_get_toplevel (flash_priv->parent);
236
screen = gtk_widget_get_screen (parent);
237
monitor = gdk_screen_get_monitor_at_window (screen,
238
gtk_widget_get_window (parent));
239
gdk_screen_get_monitor_geometry (screen, monitor, &rect);
240
gtk_window_set_transient_for (GTK_WINDOW (flash_window), GTK_WINDOW (parent));
241
gtk_window_resize (flash_window, rect.width, rect.height);
242
gtk_window_move (flash_window, rect.x, rect.y);
244
gtk_window_set_opacity (flash_window, 1);
245
gtk_widget_show_all (GTK_WIDGET (flash_window));
246
flash_priv->flash_timeout_tag = g_timeout_add (FLASH_DURATION, cheese_flash_start_fade, (gpointer) flash);
250
cheese_flash_new (GtkWidget *parent)
252
return g_object_new (CHEESE_TYPE_FLASH,