void cheese_flash_fire (CheeseFlash *flash) { CheeseFlashPrivate *flash_priv = CHEESE_FLASH_GET_PRIVATE (flash); GtkWidget *parent; GdkScreen *screen; GdkRectangle rect; int monitor; g_return_if_fail (flash_priv->parent != NULL); 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); 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); 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, 1); gtk_widget_show_all (GTK_WIDGET (flash_window)); flash_priv->flash_timeout_tag = g_timeout_add (FLASH_DURATION, cheese_flash_start_fade, (gpointer) flash); }
static void cheese_flash_init (CheeseFlash *self) { CheeseFlashPrivate *priv = CHEESE_FLASH_GET_PRIVATE (self); GtkWindow *window; 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); /* Don't take focus */ gtk_window_set_accept_focus (window, FALSE); gtk_window_set_focus_on_map (window, FALSE); /* Don't consume input */ gtk_widget_realize (GTK_WIDGET (window)); GdkRegion *input_region; input_region = gdk_region_new (); gdk_window_input_shape_combine_region (gtk_widget_get_window (GTK_WIDGET (window)), input_region, 0, 0); gdk_region_destroy (input_region); g_signal_connect (G_OBJECT (window), "expose-event", G_CALLBACK (cheese_flash_window_expose_event_cb), NULL); priv->window = window; }
static void cheese_flash_init (CheeseFlash *self) { CheeseFlashPrivate *priv = self->priv = CHEESE_FLASH_GET_PRIVATE (self); cairo_region_t *input_region; GtkWindow *window = GTK_WINDOW (self); const GdkRGBA white = { 1.0, 1.0, 1.0, 1.0 }; priv->flash_timeout_tag = 0; priv->fade_timeout_tag = 0; /* 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); /* Don't take focus */ gtk_window_set_accept_focus (window, FALSE); gtk_window_set_focus_on_map (window, FALSE); /* Make it white */ gtk_widget_override_background_color (GTK_WIDGET (window), GTK_STATE_NORMAL, &white); /* 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); }
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 gboolean cheese_flash_start_fade (gpointer data) { CheeseFlashPrivate *flash_priv = CHEESE_FLASH_GET_PRIVATE (CHEESE_FLASH (data)); 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 (1000.0 / FLASH_ANIMATION_RATE, cheese_flash_opacity_fade, data); return FALSE; }
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_widget_set_opacity (GTK_WIDGET (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); }
static void cheese_flash_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { CheeseFlashPrivate *priv = CHEESE_FLASH_GET_PRIVATE (object); 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; } }