[gnome-flashback] Add libautomount-manager
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-flashback] Add libautomount-manager
- Date: Sun, 19 Oct 2014 20:48:10 +0000 (UTC)
commit 87aa3382824a806bcb06692b63981df1792a4ef7
Author: Balló György <ballogyor gmail com>
Date: Sat Oct 18 22:45:08 2014 +0200
Add libautomount-manager
It was previously in gnome-settings-daemon.
configure.ac | 5 +
data/org.gnome.gnome-flashback.gschema.xml.in.in | 5 +
gnome-flashback/Makefile.am | 2 +
gnome-flashback/flashback-application.c | 22 +-
gnome-flashback/libautomount-manager/Makefile.am | 17 +
.../libautomount-manager/gsd-automount-manager.c | 571 ++++++++++++
.../libautomount-manager/gsd-automount-manager.h | 58 ++
gnome-flashback/libautomount-manager/gsd-autorun.c | 975 ++++++++++++++++++++
gnome-flashback/libautomount-manager/gsd-autorun.h | 53 ++
po/POTFILES.in | 2 +
10 files changed, 1709 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 1ced253..6f5ee7c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -44,6 +44,10 @@ PKG_CHECK_MODULES(END_SESSION_DIALOG, gtk+-3.0 >= $GTK_REQUIRED)
AC_SUBST(END_SESSION_DIALOG_CFLAGS)
AC_SUBST(END_SESSION_DIALOG_LIBS)
+PKG_CHECK_MODULES(AUTOMOUNT_MANAGER, gtk+-3.0 >= $GTK_REQUIRED)
+AC_SUBST(AUTOMOUNT_MANAGER_CFLAGS)
+AC_SUBST(AUTOMOUNT_MANAGER_LIBS)
+
PKG_CHECK_MODULES(DESKTOP_BACKGROUND, gtk+-3.0 >= $GTK_REQUIRED gnome-desktop-3.0 >=
$LIBGNOME_DESKTOP_REQUIRED)
AC_SUBST(DESKTOP_BACKGROUND_CFLAGS)
AC_SUBST(DESKTOP_BACKGROUND_LIBS)
@@ -67,6 +71,7 @@ AC_CONFIG_FILES([
Makefile
data/Makefile
gnome-flashback/Makefile
+gnome-flashback/libautomount-manager/Makefile
gnome-flashback/libdesktop-background/Makefile
gnome-flashback/libdisplay-config/Makefile
gnome-flashback/libend-session-dialog/Makefile
diff --git a/data/org.gnome.gnome-flashback.gschema.xml.in.in
b/data/org.gnome.gnome-flashback.gschema.xml.in.in
index 38ed32b..5c766a2 100644
--- a/data/org.gnome.gnome-flashback.gschema.xml.in.in
+++ b/data/org.gnome.gnome-flashback.gschema.xml.in.in
@@ -1,5 +1,10 @@
<schemalist gettext-domain="@GETTEXT_PACKAGE@">
<schema id="org.gnome.gnome-flashback" path="/org/gnome/gnome-flashback/">
+ <key name="automount-manager" type="b">
+ <default>true</default>
+ <_summary>Automount manager</_summary>
+ <_description>If set to true, then GNOME Flashback application will be used to
automount removable media.</_description>
+ </key>
<key name="desktop-background" type="b">
<default>true</default>
<_summary>Desktop background</_summary>
diff --git a/gnome-flashback/Makefile.am b/gnome-flashback/Makefile.am
index 48f1b50..14f3e08 100644
--- a/gnome-flashback/Makefile.am
+++ b/gnome-flashback/Makefile.am
@@ -1,4 +1,5 @@
SUBDIRS = \
+ libautomount-manager \
libdesktop-background \
libdisplay-config \
libend-session-dialog \
@@ -20,6 +21,7 @@ gnome_flashback_SOURCES = \
gnome_flashback_LDADD = \
$(GNOME_FLASHBACK_LIBS) \
+ $(top_builddir)/gnome-flashback/libautomount-manager/libautomount-manager.la \
$(top_builddir)/gnome-flashback/libdesktop-background/libdesktop-background.la \
$(top_builddir)/gnome-flashback/libdisplay-config/libdisplay-config.la \
$(top_builddir)/gnome-flashback/libend-session-dialog/libend-session-dialog.la \
diff --git a/gnome-flashback/flashback-application.c b/gnome-flashback/flashback-application.c
index dc5afda..2375229 100644
--- a/gnome-flashback/flashback-application.c
+++ b/gnome-flashback/flashback-application.c
@@ -19,6 +19,7 @@
#include <gtk/gtk.h>
#include "config.h"
#include "flashback-application.h"
+#include "libautomount-manager/gsd-automount-manager.h"
#include "libdesktop-background/desktop-background.h"
#include "libdisplay-config/flashback-display-config.h"
#include "libend-session-dialog/flashback-end-session-dialog.h"
@@ -26,6 +27,7 @@
#include "libsound-applet/gvc-applet.h"
#define FLASHBACK_SCHEMA "org.gnome.gnome-flashback"
+#define KEY_AUTOMOUNT_MANAGER "automount-manager"
#define KEY_DESKTOP_BACKGROUND "desktop-background"
#define KEY_DISPLAY_CONFIG "display-config"
#define KEY_END_SESSION_DIALOG "end-session-dialog"
@@ -34,7 +36,7 @@
struct _FlashbackApplicationPrivate {
GSettings *settings;
-
+ GsdAutomountManager *automount;
DesktopBackground *background;
FlashbackDisplayConfig *config;
FlashbackEndSessionDialog *dialog;
@@ -51,6 +53,19 @@ flashback_application_settings_changed (GSettings *settings,
{
FlashbackApplication *app = FLASHBACK_APPLICATION (user_data);
+ if (key == NULL || g_strcmp0 (key, KEY_AUTOMOUNT_MANAGER) == 0) {
+ if (g_settings_get_boolean (settings, KEY_AUTOMOUNT_MANAGER)) {
+ if (app->priv->automount == NULL) {
+ app->priv->automount = gsd_automount_manager_new ();
+ }
+ } else {
+ if (app->priv->automount) {
+ g_object_unref (app->priv->automount);
+ app->priv->automount = NULL;
+ }
+ }
+ }
+
if (key == NULL || g_strcmp0 (key, KEY_DESKTOP_BACKGROUND) == 0) {
if (g_settings_get_boolean (settings, KEY_DESKTOP_BACKGROUND)) {
if (app->priv->background == NULL) {
@@ -147,6 +162,11 @@ flashback_application_shutdown (GApplication *application)
{
FlashbackApplication *app = FLASHBACK_APPLICATION (application);
+ if (app->priv->automount) {
+ g_object_unref (app->priv->automount);
+ app->priv->automount = NULL;
+ }
+
if (app->priv->background) {
g_object_unref (app->priv->background);
app->priv->background = NULL;
diff --git a/gnome-flashback/libautomount-manager/Makefile.am
b/gnome-flashback/libautomount-manager/Makefile.am
new file mode 100644
index 0000000..d73127b
--- /dev/null
+++ b/gnome-flashback/libautomount-manager/Makefile.am
@@ -0,0 +1,17 @@
+noinst_LTLIBRARIES = \
+ libautomount-manager.la
+
+AM_CPPFLAGS = \
+ $(AUTOMOUNT_MANAGER_CFLAGS) \
+ -I$(top_builddir)/gnome-flashback/libautomount-manager
+
+libautomount_manager_la_SOURCES = \
+ gsd-automount-manager.c \
+ gsd-automount-manager.h \
+ gsd-autorun.c \
+ gsd-autorun.h
+
+libautomount_manager_la_LIBADD = \
+ $(AUTOMOUNT_MANAGER_LIBS)
+
+-include $(top_srcdir)/git.mk
diff --git a/gnome-flashback/libautomount-manager/gsd-automount-manager.c
b/gnome-flashback/libautomount-manager/gsd-automount-manager.c
new file mode 100644
index 0000000..ffd22c8
--- /dev/null
+++ b/gnome-flashback/libautomount-manager/gsd-automount-manager.c
@@ -0,0 +1,571 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Tomas Bzatek <tbzatek redhat com>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include "gsd-automount-manager.h"
+#include "gsd-autorun.h"
+
+#define GSD_AUTOMOUNT_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_AUTOMOUNT_MANAGER,
GsdAutomountManagerPrivate))
+
+#define GNOME_SESSION_DBUS_NAME "org.gnome.SessionManager"
+#define GNOME_SESSION_DBUS_OBJECT "/org/gnome/SessionManager"
+#define GNOME_SESSION_DBUS_INTERFACE "org.gnome.SessionManager"
+
+struct GsdAutomountManagerPrivate
+{
+ GSettings *settings;
+
+ GVolumeMonitor *volume_monitor;
+ unsigned int automount_idle_id;
+
+ GDBusProxy *session;
+ gboolean session_is_active;
+ gboolean screensaver_active;
+ guint ss_watch_id;
+ GDBusProxy *ss_proxy;
+
+ GList *volume_queue;
+};
+
+static void gsd_automount_manager_class_init (GsdAutomountManagerClass *klass);
+static void gsd_automount_manager_init (GsdAutomountManager *gsd_automount_manager);
+
+G_DEFINE_TYPE (GsdAutomountManager, gsd_automount_manager, G_TYPE_OBJECT)
+
+GDBusProxy *
+get_session_proxy (void)
+{
+ static GDBusProxy *session_proxy;
+ GError *error = NULL;
+
+ if (session_proxy != NULL) {
+ g_object_ref (session_proxy);
+ } else {
+ session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ GNOME_SESSION_DBUS_NAME,
+ GNOME_SESSION_DBUS_OBJECT,
+ GNOME_SESSION_DBUS_INTERFACE,
+ NULL,
+ &error);
+ if (error) {
+ g_warning ("Failed to connect to the session manager: %s", error->message);
+ g_error_free (error);
+ } else {
+ g_object_add_weak_pointer (G_OBJECT (session_proxy), (gpointer*)&session_proxy);
+ }
+ }
+
+ return session_proxy;
+}
+
+static GtkDialog *
+show_error_dialog (const char *primary_text,
+ const char *secondary_text)
+{
+ GtkWidget *dialog;
+
+ dialog = gtk_message_dialog_new (NULL,
+ 0,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ "%s", "");
+
+ g_object_set (dialog,
+ "text", primary_text,
+ "secondary-text", secondary_text,
+ NULL);
+
+ gtk_widget_show (GTK_WIDGET (dialog));
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+ return GTK_DIALOG (dialog);
+}
+
+static void
+startup_volume_mount_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_volume_mount_finish (G_VOLUME (source_object), res, NULL);
+}
+
+static void
+automount_all_volumes (GsdAutomountManager *manager)
+{
+ GList *volumes, *l;
+ GMount *mount;
+ GVolume *volume;
+
+ if (g_settings_get_boolean (manager->priv->settings, "automount")) {
+ /* automount all mountable volumes at start-up */
+ volumes = g_volume_monitor_get_volumes (manager->priv->volume_monitor);
+ for (l = volumes; l != NULL; l = l->next) {
+ volume = l->data;
+
+ if (!g_volume_should_automount (volume) ||
+ !g_volume_can_mount (volume)) {
+ continue;
+ }
+
+ mount = g_volume_get_mount (volume);
+ if (mount != NULL) {
+ g_object_unref (mount);
+ continue;
+ }
+
+ /* pass NULL as GMountOperation to avoid user interaction */
+ g_volume_mount (volume, 0, NULL, NULL, startup_volume_mount_cb, NULL);
+ }
+ g_list_free_full (volumes, g_object_unref);
+ }
+}
+
+static gboolean
+automount_all_volumes_idle_cb (gpointer data)
+{
+ GsdAutomountManager *manager = GSD_AUTOMOUNT_MANAGER (data);
+
+ automount_all_volumes (manager);
+
+ manager->priv->automount_idle_id = 0;
+ return FALSE;
+}
+
+static void
+volume_mount_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GMountOperation *mount_op = user_data;
+ GError *error;
+ char *primary;
+ char *name;
+
+ error = NULL;
+ gsd_allow_autorun_for_volume_finish (G_VOLUME (source_object));
+ if (!g_volume_mount_finish (G_VOLUME (source_object), res, &error)) {
+ if (error->code != G_IO_ERROR_FAILED_HANDLED) {
+ name = g_volume_get_name (G_VOLUME (source_object));
+ primary = g_strdup_printf (_("Unable to mount %s"), name);
+ g_free (name);
+ show_error_dialog (primary,
+ error->message);
+ g_free (primary);
+ }
+ g_error_free (error);
+ }
+
+ g_object_unref (mount_op);
+}
+
+static void
+do_mount_volume (GVolume *volume)
+{
+ GMountOperation *mount_op;
+
+ mount_op = gtk_mount_operation_new (NULL);
+ g_mount_operation_set_password_save (mount_op, G_PASSWORD_SAVE_FOR_SESSION);
+
+ gsd_allow_autorun_for_volume (volume);
+ g_volume_mount (volume, 0, mount_op, NULL, volume_mount_cb, mount_op);
+}
+
+static void
+check_volume_queue (GsdAutomountManager *manager)
+{
+ GList *l;
+ GVolume *volume;
+
+ if (manager->priv->screensaver_active)
+ return;
+
+ l = manager->priv->volume_queue;
+
+ while (l != NULL) {
+ volume = l->data;
+
+ do_mount_volume (volume);
+ manager->priv->volume_queue =
+ g_list_remove (manager->priv->volume_queue, volume);
+
+ g_object_unref (volume);
+ l = l->next;
+ }
+
+ manager->priv->volume_queue = NULL;
+}
+
+static void
+check_screen_lock_and_mount (GsdAutomountManager *manager,
+ GVolume *volume)
+{
+ if (!manager->priv->session_is_active)
+ return;
+
+ if (manager->priv->screensaver_active) {
+ /* queue the volume, to mount it after the screensaver state changed */
+ g_debug ("Queuing volume %p", volume);
+ manager->priv->volume_queue = g_list_prepend (manager->priv->volume_queue,
+ g_object_ref (volume));
+ } else {
+ /* mount it immediately */
+ do_mount_volume (volume);
+ }
+}
+
+static void
+volume_removed_callback (GVolumeMonitor *monitor,
+ GVolume *volume,
+ GsdAutomountManager *manager)
+{
+ g_debug ("Volume %p removed, removing from the queue", volume);
+
+ /* clear it from the queue, if present */
+ manager->priv->volume_queue =
+ g_list_remove (manager->priv->volume_queue, volume);
+}
+
+static void
+volume_added_callback (GVolumeMonitor *monitor,
+ GVolume *volume,
+ GsdAutomountManager *manager)
+{
+ if (g_settings_get_boolean (manager->priv->settings, "automount") &&
+ g_volume_should_automount (volume) &&
+ g_volume_can_mount (volume)) {
+ check_screen_lock_and_mount (manager, volume);
+ } else {
+ /* Allow gsd_autorun() to run. When the mount is later
+ * added programmatically (i.e. for a blank CD),
+ * gsd_autorun() will be called by mount_added_callback(). */
+ gsd_allow_autorun_for_volume (volume);
+ gsd_allow_autorun_for_volume_finish (volume);
+ }
+}
+
+static void
+autorun_show_window (GMount *mount, gpointer user_data)
+{
+ GFile *location;
+ char *uri;
+ GError *error;
+ char *primary;
+ char *name;
+
+ location = g_mount_get_root (mount);
+ uri = g_file_get_uri (location);
+
+ error = NULL;
+ /* use default folder handler */
+ if (! gtk_show_uri (NULL, uri, GDK_CURRENT_TIME, &error)) {
+ name = g_mount_get_name (mount);
+ primary = g_strdup_printf (_("Unable to open a folder for %s"), name);
+ g_free (name);
+ show_error_dialog (primary,
+ error->message);
+ g_free (primary);
+ g_error_free (error);
+ }
+
+ g_free (uri);
+ g_object_unref (location);
+}
+
+static void
+mount_added_callback (GVolumeMonitor *monitor,
+ GMount *mount,
+ GsdAutomountManager *manager)
+{
+ /* don't autorun if the session is not active */
+ if (!manager->priv->session_is_active) {
+ return;
+ }
+
+ gsd_autorun (mount, manager->priv->settings, autorun_show_window, manager);
+}
+
+
+static void
+session_props_changed (GDBusProxy *session, GVariant *v, char **props, gpointer user_data)
+{
+ GsdAutomountManager *manager = user_data;
+ GsdAutomountManagerPrivate *p = manager->priv;
+ GVariant *active_v = NULL;
+ gboolean is_active;
+
+ active_v = g_dbus_proxy_get_cached_property (session, "SessionIsActive");
+ if (!active_v)
+ return;
+
+ g_variant_get (active_v, "b", &is_active);
+ g_variant_unref (active_v);
+ g_printerr ("AUTOMOUNT: session is active: %d -> %d\n", p->session_is_active, is_active);
+ p->session_is_active = is_active;
+
+ if (!p->session_is_active) {
+ if (p->volume_queue != NULL) {
+ g_list_free_full (p->volume_queue, g_object_unref);
+ p->volume_queue = NULL;
+ }
+ }
+}
+
+static void
+do_initialize_session (GsdAutomountManager *manager)
+{
+ manager->priv->session = get_session_proxy ();
+ g_signal_connect (manager->priv->session, "g-properties-changed",
+ G_CALLBACK (session_props_changed), manager);
+ session_props_changed (manager->priv->session, NULL, NULL, manager);
+}
+
+#define SCREENSAVER_NAME "org.gnome.ScreenSaver"
+#define SCREENSAVER_PATH "/org/gnome/ScreenSaver"
+#define SCREENSAVER_INTERFACE "org.gnome.ScreenSaver"
+
+static void
+screensaver_signal_callback (GDBusProxy *proxy,
+ const gchar *sender_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ GsdAutomountManager *manager = user_data;
+
+ if (g_strcmp0 (signal_name, "ActiveChanged") == 0) {
+ g_variant_get (parameters, "(b)", &manager->priv->screensaver_active);
+ g_debug ("Screensaver active changed to %d", manager->priv->screensaver_active);
+
+ check_volume_queue (manager);
+ }
+}
+
+static void
+screensaver_get_active_ready_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GsdAutomountManager *manager = user_data;
+ GDBusProxy *proxy = manager->priv->ss_proxy;
+ GVariant *result;
+ GError *error = NULL;
+
+ result = g_dbus_proxy_call_finish (proxy,
+ res,
+ &error);
+
+ if (error != NULL) {
+ g_warning ("Can't call GetActive() on the ScreenSaver object: %s",
+ error->message);
+ g_error_free (error);
+
+ return;
+ }
+
+ g_variant_get (result, "(b)", &manager->priv->screensaver_active);
+ g_variant_unref (result);
+
+ g_debug ("Screensaver GetActive() returned %d", manager->priv->screensaver_active);
+}
+
+static void
+screensaver_proxy_ready_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GsdAutomountManager *manager = user_data;
+ GError *error = NULL;
+ GDBusProxy *ss_proxy;
+
+ ss_proxy = g_dbus_proxy_new_finish (res, &error);
+
+ if (error != NULL) {
+ g_warning ("Can't get proxy for the ScreenSaver object: %s",
+ error->message);
+ g_error_free (error);
+
+ return;
+ }
+
+ g_debug ("ScreenSaver proxy ready");
+
+ manager->priv->ss_proxy = ss_proxy;
+
+ g_signal_connect (ss_proxy, "g-signal",
+ G_CALLBACK (screensaver_signal_callback), manager);
+
+ g_dbus_proxy_call (ss_proxy,
+ "GetActive",
+ NULL,
+ G_DBUS_CALL_FLAGS_NO_AUTO_START,
+ -1,
+ NULL,
+ screensaver_get_active_ready_cb,
+ manager);
+}
+
+static void
+screensaver_appeared_callback (GDBusConnection *connection,
+ const gchar *name,
+ const gchar *name_owner,
+ gpointer user_data)
+{
+ GsdAutomountManager *manager = user_data;
+
+ g_debug ("ScreenSaver name appeared");
+
+ manager->priv->screensaver_active = FALSE;
+
+ g_dbus_proxy_new (connection,
+ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+ NULL,
+ name,
+ SCREENSAVER_PATH,
+ SCREENSAVER_INTERFACE,
+ NULL,
+ screensaver_proxy_ready_cb,
+ manager);
+}
+
+static void
+screensaver_vanished_callback (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ GsdAutomountManager *manager = user_data;
+
+ g_debug ("ScreenSaver name vanished");
+
+ manager->priv->screensaver_active = FALSE;
+ g_clear_object (&manager->priv->ss_proxy);
+
+ /* in this case force a clear of the volume queue, without
+ * mounting them.
+ */
+ if (manager->priv->volume_queue != NULL) {
+ g_list_free_full (manager->priv->volume_queue, g_object_unref);
+ manager->priv->volume_queue = NULL;
+ }
+}
+
+static void
+do_initialize_screensaver (GsdAutomountManager *manager)
+{
+ GsdAutomountManagerPrivate *p = manager->priv;
+
+ p->ss_watch_id =
+ g_bus_watch_name (G_BUS_TYPE_SESSION,
+ SCREENSAVER_NAME,
+ G_BUS_NAME_WATCHER_FLAGS_NONE,
+ screensaver_appeared_callback,
+ screensaver_vanished_callback,
+ manager,
+ NULL);
+}
+
+static void
+setup_automounter (GsdAutomountManager *manager)
+{
+ do_initialize_session (manager);
+ do_initialize_screensaver (manager);
+
+ manager->priv->volume_monitor = g_volume_monitor_get ();
+ g_signal_connect_object (manager->priv->volume_monitor, "mount-added",
+ G_CALLBACK (mount_added_callback), manager, 0);
+ g_signal_connect_object (manager->priv->volume_monitor, "volume-added",
+ G_CALLBACK (volume_added_callback), manager, 0);
+ g_signal_connect_object (manager->priv->volume_monitor, "volume-removed",
+ G_CALLBACK (volume_removed_callback), manager, 0);
+
+ manager->priv->automount_idle_id =
+ g_idle_add_full (G_PRIORITY_LOW,
+ automount_all_volumes_idle_cb,
+ manager, NULL);
+}
+
+void
+gsd_automount_manager_finalize (GObject *object)
+{
+ GsdAutomountManager *manager = GSD_AUTOMOUNT_MANAGER (object);
+ GsdAutomountManagerPrivate *p = manager->priv;
+
+ g_debug ("Stopping automounting manager");
+
+ g_clear_object (&p->session);
+ g_clear_object (&p->volume_monitor);
+ g_clear_object (&p->settings);
+ g_clear_object (&p->ss_proxy);
+
+ g_bus_unwatch_name (p->ss_watch_id);
+
+ if (p->volume_queue != NULL) {
+ g_list_free_full (p->volume_queue, g_object_unref);
+ p->volume_queue = NULL;
+ }
+
+ if (p->automount_idle_id != 0) {
+ g_source_remove (p->automount_idle_id);
+ p->automount_idle_id = 0;
+ }
+
+ G_OBJECT_CLASS (gsd_automount_manager_parent_class)->finalize (object);
+}
+
+static void
+gsd_automount_manager_init (GsdAutomountManager *manager)
+{
+ manager->priv = GSD_AUTOMOUNT_MANAGER_GET_PRIVATE (manager);
+
+ g_debug ("Starting automounting manager");
+
+ manager->priv->settings = g_settings_new ("org.gnome.desktop.media-handling");
+ setup_automounter (manager);
+}
+
+static void
+gsd_automount_manager_class_init (GsdAutomountManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gsd_automount_manager_finalize;
+
+ g_type_class_add_private (klass, sizeof (GsdAutomountManagerPrivate));
+}
+
+GsdAutomountManager *
+gsd_automount_manager_new (void)
+{
+ return GSD_AUTOMOUNT_MANAGER (g_object_new (GSD_TYPE_AUTOMOUNT_MANAGER, NULL));
+}
diff --git a/gnome-flashback/libautomount-manager/gsd-automount-manager.h
b/gnome-flashback/libautomount-manager/gsd-automount-manager.h
new file mode 100644
index 0000000..42f9f58
--- /dev/null
+++ b/gnome-flashback/libautomount-manager/gsd-automount-manager.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Tomas Bzatek <tbzatek redhat com>
+ */
+
+#ifndef __GSD_AUTOMOUNT_MANAGER_H
+#define __GSD_AUTOMOUNT_MANAGER_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GSD_TYPE_AUTOMOUNT_MANAGER (gsd_automount_manager_get_type ())
+#define GSD_AUTOMOUNT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_AUTOMOUNT_MANAGER,
GsdAutomountManager))
+#define GSD_AUTOMOUNT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_AUTOMOUNT_MANAGER,
GsdAutomountManagerClass))
+#define GSD_IS_AUTOMOUNT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_AUTOMOUNT_MANAGER))
+#define GSD_IS_AUTOMOUNT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_AUTOMOUNT_MANAGER))
+#define GSD_AUTOMOUNT_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_AUTOMOUNT_MANAGER,
GsdAutomountManagerClass))
+
+typedef struct GsdAutomountManagerPrivate GsdAutomountManagerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ GsdAutomountManagerPrivate *priv;
+} GsdAutomountManager;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} GsdAutomountManagerClass;
+
+GType gsd_automount_manager_get_type (void);
+
+GsdAutomountManager * gsd_automount_manager_new (void);
+gboolean gsd_automount_manager_start (GsdAutomountManager *manager,
+ GError **error);
+void gsd_automount_manager_stop (GsdAutomountManager *manager);
+
+G_END_DECLS
+
+#endif /* __GSD_AUTOMOUNT_MANAGER_H */
diff --git a/gnome-flashback/libautomount-manager/gsd-autorun.c
b/gnome-flashback/libautomount-manager/gsd-autorun.c
new file mode 100644
index 0000000..56031b4
--- /dev/null
+++ b/gnome-flashback/libautomount-manager/gsd-autorun.c
@@ -0,0 +1,975 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
+/*
+ * gsd-automount.c: helpers for automounting hotplugged volumes
+ *
+ * Copyright (C) 2008, 2010 Red Hat, Inc.
+ *
+ * Nautilus 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: David Zeuthen <davidz redhat com>
+ * Cosimo Cecchi <cosimoc redhat com>
+ */
+
+#include <config.h>
+#include <string.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <X11/XKBlib.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "gsd-autorun.h"
+
+static gboolean should_autorun_mount (GMount *mount);
+
+#define CUSTOM_ITEM_ASK "gsd-item-ask"
+#define CUSTOM_ITEM_DO_NOTHING "gsd-item-do-nothing"
+#define CUSTOM_ITEM_OPEN_FOLDER "gsd-item-open-folder"
+
+typedef struct
+{
+ GtkWidget *dialog;
+
+ GMount *mount;
+ gboolean should_eject;
+
+ gboolean selected_ignore;
+ gboolean selected_open_folder;
+ GAppInfo *selected_app;
+
+ gboolean remember;
+
+ char *x_content_type;
+
+ GsdAutorunOpenWindow open_window_func;
+ gpointer user_data;
+} AutorunDialogData;
+
+static int
+gsd_autorun_g_strv_find (char **strv, const char *find_me)
+{
+ guint index;
+
+ g_return_val_if_fail (find_me != NULL, -1);
+
+ for (index = 0; strv[index] != NULL; ++index) {
+ if (strcmp (strv[index], find_me) == 0) {
+ return index;
+ }
+ }
+
+ return -1;
+}
+
+
+#define ICON_SIZE_STANDARD 48
+
+static gint
+get_icon_size_for_stock_size (GtkIconSize size)
+{
+ gint w, h;
+
+ if (gtk_icon_size_lookup (size, &w, &h)) {
+ return MAX (w, h);
+ }
+ return ICON_SIZE_STANDARD;
+}
+
+static GdkPixbuf *
+render_icon (GIcon *icon, gint icon_size)
+{
+ GdkPixbuf *pixbuf;
+ GtkIconInfo *info;
+
+ pixbuf = NULL;
+
+ if (G_IS_THEMED_ICON (icon)) {
+ gchar const * const *names;
+
+ info = gtk_icon_theme_lookup_by_gicon (gtk_icon_theme_get_default (),
+ icon,
+ icon_size,
+ 0);
+
+ if (info) {
+ pixbuf = gtk_icon_info_load_icon (info, NULL);
+ gtk_icon_info_free (info);
+ }
+
+ if (pixbuf == NULL) {
+ names = g_themed_icon_get_names (G_THEMED_ICON (icon));
+ pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+ *names,
+ icon_size,
+ 0, NULL);
+ }
+ }
+ else
+ if (G_IS_FILE_ICON (icon)) {
+ GFile *icon_file;
+ gchar *path;
+
+ icon_file = g_file_icon_get_file (G_FILE_ICON (icon));
+ path = g_file_get_path (icon_file);
+ pixbuf = gdk_pixbuf_new_from_file_at_size (path,
+ icon_size, icon_size,
+ NULL);
+ g_free (path);
+ g_object_unref (G_OBJECT (icon_file));
+ }
+
+ return pixbuf;
+}
+
+static void
+gsd_autorun_get_preferences (const char *x_content_type,
+ gboolean *pref_start_app,
+ gboolean *pref_ignore,
+ gboolean *pref_open_folder)
+{
+ GSettings *settings;
+ char **x_content_start_app;
+ char **x_content_ignore;
+ char **x_content_open_folder;
+
+ g_return_if_fail (pref_start_app != NULL);
+ g_return_if_fail (pref_ignore != NULL);
+ g_return_if_fail (pref_open_folder != NULL);
+
+ settings = g_settings_new ("org.gnome.desktop.media-handling");
+
+ *pref_start_app = FALSE;
+ *pref_ignore = FALSE;
+ *pref_open_folder = FALSE;
+ x_content_start_app = g_settings_get_strv (settings, "autorun-x-content-start-app");
+ x_content_ignore = g_settings_get_strv (settings, "autorun-x-content-ignore");
+ x_content_open_folder = g_settings_get_strv (settings, "autorun-x-content-open-folder");
+ if (x_content_start_app != NULL) {
+ *pref_start_app = gsd_autorun_g_strv_find (x_content_start_app, x_content_type) != -1;
+ }
+ if (x_content_ignore != NULL) {
+ *pref_ignore = gsd_autorun_g_strv_find (x_content_ignore, x_content_type) != -1;
+ }
+ if (x_content_open_folder != NULL) {
+ *pref_open_folder = gsd_autorun_g_strv_find (x_content_open_folder, x_content_type) != -1;
+ }
+ g_strfreev (x_content_ignore);
+ g_strfreev (x_content_start_app);
+ g_strfreev (x_content_open_folder);
+ g_object_unref (settings);
+}
+
+static char **
+remove_elem_from_str_array (char **v,
+ const char *s)
+{
+ GPtrArray *array;
+ guint idx;
+
+ array = g_ptr_array_new ();
+
+ for (idx = 0; v[idx] != NULL; idx++) {
+ if (g_strcmp0 (v[idx], s) == 0) {
+ continue;
+ }
+
+ g_ptr_array_add (array, v[idx]);
+ }
+
+ g_ptr_array_add (array, NULL);
+
+ g_free (v);
+
+ return (char **) g_ptr_array_free (array, FALSE);
+}
+
+static char **
+add_elem_to_str_array (char **v,
+ const char *s)
+{
+ GPtrArray *array;
+ guint idx;
+
+ array = g_ptr_array_new ();
+
+ for (idx = 0; v[idx] != NULL; idx++) {
+ g_ptr_array_add (array, v[idx]);
+ }
+
+ g_ptr_array_add (array, g_strdup (s));
+ g_ptr_array_add (array, NULL);
+
+ g_free (v);
+
+ return (char **) g_ptr_array_free (array, FALSE);
+}
+
+static void
+gsd_autorun_set_preferences (const char *x_content_type,
+ gboolean pref_start_app,
+ gboolean pref_ignore,
+ gboolean pref_open_folder)
+{
+ GSettings *settings;
+ char **x_content_start_app;
+ char **x_content_ignore;
+ char **x_content_open_folder;
+
+ g_assert (x_content_type != NULL);
+
+ settings = g_settings_new ("org.gnome.desktop.media-handling");
+
+ x_content_start_app = g_settings_get_strv (settings, "autorun-x-content-start-app");
+ x_content_ignore = g_settings_get_strv (settings, "autorun-x-content-ignore");
+ x_content_open_folder = g_settings_get_strv (settings, "autorun-x-content-open-folder");
+
+ x_content_start_app = remove_elem_from_str_array (x_content_start_app, x_content_type);
+ if (pref_start_app) {
+ x_content_start_app = add_elem_to_str_array (x_content_start_app, x_content_type);
+ }
+ g_settings_set_strv (settings, "autorun-x-content-start-app", (const gchar * const*)
x_content_start_app);
+
+ x_content_ignore = remove_elem_from_str_array (x_content_ignore, x_content_type);
+ if (pref_ignore) {
+ x_content_ignore = add_elem_to_str_array (x_content_ignore, x_content_type);
+ }
+ g_settings_set_strv (settings, "autorun-x-content-ignore", (const gchar * const*) x_content_ignore);
+
+ x_content_open_folder = remove_elem_from_str_array (x_content_open_folder, x_content_type);
+ if (pref_open_folder) {
+ x_content_open_folder = add_elem_to_str_array (x_content_open_folder, x_content_type);
+ }
+ g_settings_set_strv (settings, "autorun-x-content-open-folder", (const gchar * const*)
x_content_open_folder);
+
+ g_strfreev (x_content_open_folder);
+ g_strfreev (x_content_ignore);
+ g_strfreev (x_content_start_app);
+ g_object_unref (settings);
+}
+
+static void
+custom_item_activated_cb (GtkAppChooserButton *button,
+ const gchar *item,
+ gpointer user_data)
+{
+ gchar *content_type;
+ AutorunDialogData *data = user_data;
+
+ content_type = gtk_app_chooser_get_content_type (GTK_APP_CHOOSER (button));
+
+ if (g_strcmp0 (item, CUSTOM_ITEM_ASK) == 0) {
+ gsd_autorun_set_preferences (content_type,
+ FALSE, FALSE, FALSE);
+ data->selected_open_folder = FALSE;
+ data->selected_ignore = FALSE;
+ } else if (g_strcmp0 (item, CUSTOM_ITEM_OPEN_FOLDER) == 0) {
+ gsd_autorun_set_preferences (content_type,
+ FALSE, FALSE, TRUE);
+ data->selected_open_folder = TRUE;
+ data->selected_ignore = FALSE;
+ } else if (g_strcmp0 (item, CUSTOM_ITEM_DO_NOTHING) == 0) {
+ gsd_autorun_set_preferences (content_type,
+ FALSE, TRUE, FALSE);
+ data->selected_open_folder = FALSE;
+ data->selected_ignore = TRUE;
+ }
+
+ g_free (content_type);
+}
+
+static void
+combo_box_changed_cb (GtkComboBox *combo_box,
+ gpointer user_data)
+{
+ GAppInfo *info;
+ AutorunDialogData *data = user_data;
+
+ info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (combo_box));
+
+ if (info == NULL)
+ return;
+
+ g_clear_object (&data->selected_app);
+ data->selected_app = info;
+}
+
+static void
+prepare_combo_box (GtkWidget *combo_box,
+ AutorunDialogData *data)
+{
+ GtkAppChooserButton *app_chooser = GTK_APP_CHOOSER_BUTTON (combo_box);
+ GIcon *icon;
+ gboolean pref_ask;
+ gboolean pref_start_app;
+ gboolean pref_ignore;
+ gboolean pref_open_folder;
+ GAppInfo *info;
+ gchar *content_type;
+
+ content_type = gtk_app_chooser_get_content_type (GTK_APP_CHOOSER (app_chooser));
+
+ /* fetch preferences for this content type */
+ gsd_autorun_get_preferences (content_type,
+ &pref_start_app, &pref_ignore, &pref_open_folder);
+ pref_ask = !pref_start_app && !pref_ignore && !pref_open_folder;
+
+ info = gtk_app_chooser_get_app_info (GTK_APP_CHOOSER (combo_box));
+
+ /* append the separator only if we have >= 1 apps in the chooser */
+ if (info != NULL) {
+ gtk_app_chooser_button_append_separator (app_chooser);
+ g_object_unref (info);
+ }
+
+ icon = g_themed_icon_new (GTK_STOCK_DIALOG_QUESTION);
+ gtk_app_chooser_button_append_custom_item (app_chooser, CUSTOM_ITEM_ASK,
+ _("Ask what to do"),
+ icon);
+ g_object_unref (icon);
+
+ icon = g_themed_icon_new (GTK_STOCK_CLOSE);
+ gtk_app_chooser_button_append_custom_item (app_chooser, CUSTOM_ITEM_DO_NOTHING,
+ _("Do Nothing"),
+ icon);
+ g_object_unref (icon);
+
+ icon = g_themed_icon_new ("folder-open");
+ gtk_app_chooser_button_append_custom_item (app_chooser, CUSTOM_ITEM_OPEN_FOLDER,
+ _("Open Folder"),
+ icon);
+ g_object_unref (icon);
+
+ gtk_app_chooser_button_set_show_dialog_item (app_chooser, TRUE);
+
+ if (pref_ask) {
+ gtk_app_chooser_button_set_active_custom_item (app_chooser, CUSTOM_ITEM_ASK);
+ } else if (pref_ignore) {
+ gtk_app_chooser_button_set_active_custom_item (app_chooser, CUSTOM_ITEM_DO_NOTHING);
+ } else if (pref_open_folder) {
+ gtk_app_chooser_button_set_active_custom_item (app_chooser, CUSTOM_ITEM_OPEN_FOLDER);
+ }
+
+ g_signal_connect (app_chooser, "changed",
+ G_CALLBACK (combo_box_changed_cb), data);
+ g_signal_connect (app_chooser, "custom-item-activated",
+ G_CALLBACK (custom_item_activated_cb), data);
+
+ g_free (content_type);
+}
+
+static gboolean
+is_shift_pressed (void)
+{
+ gboolean ret;
+ XkbStateRec state;
+ Bool status;
+
+ ret = FALSE;
+
+ gdk_error_trap_push ();
+ status = XkbGetState (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
+ XkbUseCoreKbd, &state);
+ gdk_error_trap_pop_ignored ();
+
+ if (status == Success) {
+ ret = state.mods & ShiftMask;
+ }
+
+ return ret;
+}
+
+enum {
+ AUTORUN_DIALOG_RESPONSE_EJECT = 0
+};
+
+static void
+gsd_autorun_launch_for_mount (GMount *mount, GAppInfo *app_info)
+{
+ GFile *root;
+ GdkAppLaunchContext *launch_context;
+ GError *error;
+ gboolean result;
+ GList *list;
+ gchar *uri_scheme;
+ gchar *uri;
+
+ root = g_mount_get_root (mount);
+ list = g_list_append (NULL, root);
+
+ launch_context = gdk_app_launch_context_new ();
+
+ error = NULL;
+ result = g_app_info_launch (app_info,
+ list,
+ G_APP_LAUNCH_CONTEXT (launch_context),
+ &error);
+
+ g_object_unref (launch_context);
+
+ if (!result) {
+ if (error->domain == G_IO_ERROR &&
+ error->code == G_IO_ERROR_NOT_SUPPORTED) {
+ uri = g_file_get_uri (root);
+ uri_scheme = g_uri_parse_scheme (uri);
+
+ /* FIXME: Present user a dialog to choose another app when the last one failed to
handle a file */
+ g_warning ("Cannot open location: %s\n", error->message);
+
+ g_free (uri_scheme);
+ g_free (uri);
+ } else {
+ g_warning ("Cannot open app: %s\n", error->message);
+ }
+ g_error_free (error);
+ }
+
+ g_list_free (list);
+ g_object_unref (root);
+}
+
+static void autorun_dialog_mount_unmounted (GMount *mount, AutorunDialogData *data);
+
+static void
+autorun_dialog_destroy (AutorunDialogData *data)
+{
+ g_signal_handlers_disconnect_by_func (G_OBJECT (data->mount),
+ G_CALLBACK (autorun_dialog_mount_unmounted),
+ data);
+
+ gtk_widget_destroy (GTK_WIDGET (data->dialog));
+ if (data->selected_app != NULL) {
+ g_object_unref (data->selected_app);
+ }
+ g_object_unref (data->mount);
+ g_free (data->x_content_type);
+ g_free (data);
+}
+
+static void
+autorun_dialog_mount_unmounted (GMount *mount, AutorunDialogData *data)
+{
+ /* remove the dialog if the media is unmounted */
+ autorun_dialog_destroy (data);
+}
+
+static void
+unmount_mount_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *error;
+ char *primary;
+ gboolean unmounted;
+ gboolean should_eject;
+ GtkWidget *dialog;
+
+
+ should_eject = user_data != NULL;
+
+ error = NULL;
+ if (should_eject) {
+ unmounted = g_mount_eject_with_operation_finish (G_MOUNT (source_object),
+ res, &error);
+ } else {
+ unmounted = g_mount_unmount_with_operation_finish (G_MOUNT (source_object),
+ res, &error);
+ }
+
+ if (! unmounted) {
+ if (error->code != G_IO_ERROR_FAILED_HANDLED) {
+ if (should_eject) {
+ primary = g_strdup_printf (_("Unable to eject %p"), source_object);
+ } else {
+ primary = g_strdup_printf (_("Unable to unmount %p"), source_object);
+ }
+
+ dialog = gtk_message_dialog_new (NULL,
+ 0,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_OK,
+ "%s",
+ primary);
+ gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog),
+ "%s",
+ error->message);
+
+ gtk_widget_show (GTK_WIDGET (dialog));
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+ g_free (primary);
+ }
+ }
+
+ if (error != NULL) {
+ g_error_free (error);
+ }
+}
+
+static void
+do_unmount (GMount *mount, gboolean should_eject, GtkWindow *window)
+{
+ GMountOperation *mount_op;
+
+ mount_op = gtk_mount_operation_new (window);
+ if (should_eject) {
+ g_mount_eject_with_operation (mount,
+ 0,
+ mount_op,
+ NULL,
+ unmount_mount_callback,
+ (gpointer) 1);
+ } else {
+ g_mount_unmount_with_operation (mount,
+ 0,
+ mount_op,
+ NULL,
+ unmount_mount_callback,
+ (gpointer) 0);
+ }
+ g_object_unref (mount_op);
+}
+
+static void
+autorun_dialog_response (GtkDialog *dialog, gint response, AutorunDialogData *data)
+{
+ switch (response) {
+ case AUTORUN_DIALOG_RESPONSE_EJECT:
+ do_unmount (data->mount, data->should_eject, GTK_WINDOW (dialog));
+ break;
+
+ case GTK_RESPONSE_NONE:
+ /* window was closed */
+ break;
+ case GTK_RESPONSE_CANCEL:
+ break;
+ case GTK_RESPONSE_OK:
+ /* do the selected action */
+
+ if (data->remember) {
+ /* make sure we don't ask again */
+ gsd_autorun_set_preferences (data->x_content_type, TRUE, data->selected_ignore,
data->selected_open_folder);
+ if (!data->selected_ignore && !data->selected_open_folder && data->selected_app !=
NULL) {
+ g_app_info_set_as_default_for_type (data->selected_app,
+ data->x_content_type,
+ NULL);
+ }
+ } else {
+ /* make sure we do ask again */
+ gsd_autorun_set_preferences (data->x_content_type, FALSE, FALSE, FALSE);
+ }
+
+ if (!data->selected_ignore && !data->selected_open_folder && data->selected_app != NULL) {
+ gsd_autorun_launch_for_mount (data->mount, data->selected_app);
+ } else if (!data->selected_ignore && data->selected_open_folder) {
+ if (data->open_window_func != NULL)
+ data->open_window_func (data->mount, data->user_data);
+ }
+ break;
+ }
+
+ autorun_dialog_destroy (data);
+}
+
+static void
+autorun_always_toggled (GtkToggleButton *togglebutton, AutorunDialogData *data)
+{
+ data->remember = gtk_toggle_button_get_active (togglebutton);
+}
+
+static gboolean
+combo_box_enter_ok (GtkWidget *togglebutton, GdkEventKey *event, GtkDialog *dialog)
+{
+ if (event->keyval == GDK_KEY_KP_Enter || event->keyval == GDK_KEY_Return) {
+ gtk_dialog_response (dialog, GTK_RESPONSE_OK);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* returns TRUE if a folder window should be opened */
+static gboolean
+do_autorun_for_content_type (GMount *mount,
+ const char *x_content_type,
+ GsdAutorunOpenWindow open_window_func,
+ gpointer user_data)
+{
+ AutorunDialogData *data;
+ GtkWidget *dialog;
+ GtkWidget *hbox;
+ GtkWidget *vbox;
+ GtkWidget *label;
+ GtkWidget *combo_box;
+ GtkWidget *always_check_button;
+ GtkWidget *eject_button;
+ GtkWidget *image;
+ char *markup;
+ char *content_description;
+ char *mount_name;
+ GIcon *icon;
+ GdkPixbuf *pixbuf;
+ int icon_size;
+ gboolean user_forced_dialog;
+ gboolean pref_ask;
+ gboolean pref_start_app;
+ gboolean pref_ignore;
+ gboolean pref_open_folder;
+ char *media_greeting;
+ gboolean ret;
+
+ ret = FALSE;
+ mount_name = NULL;
+
+ if (g_content_type_is_a (x_content_type, "x-content/win32-software")) {
+ /* don't pop up the dialog anyway if the content type says
+ * windows software.
+ */
+ goto out;
+ }
+
+ user_forced_dialog = is_shift_pressed ();
+
+ gsd_autorun_get_preferences (x_content_type, &pref_start_app, &pref_ignore, &pref_open_folder);
+ pref_ask = !pref_start_app && !pref_ignore && !pref_open_folder;
+
+ if (user_forced_dialog) {
+ goto show_dialog;
+ }
+
+ if (!pref_ask && !pref_ignore && !pref_open_folder) {
+ GAppInfo *app_info;
+ app_info = g_app_info_get_default_for_type (x_content_type, FALSE);
+ if (app_info != NULL) {
+ gsd_autorun_launch_for_mount (mount, app_info);
+ }
+ goto out;
+ }
+
+ if (pref_open_folder) {
+ ret = TRUE;
+ goto out;
+ }
+
+ if (pref_ignore) {
+ goto out;
+ }
+
+show_dialog:
+
+ mount_name = g_mount_get_name (mount);
+
+ dialog = gtk_dialog_new ();
+
+ hbox = gtk_hbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), hbox, TRUE, TRUE, 0);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox), 12);
+
+ icon = g_mount_get_icon (mount);
+ icon_size = get_icon_size_for_stock_size (GTK_ICON_SIZE_DIALOG);
+ image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_DIALOG);
+ pixbuf = render_icon (icon, icon_size);
+ gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
+ gtk_box_pack_start (GTK_BOX (hbox), image, TRUE, TRUE, 0);
+ /* also use the icon on the dialog */
+ gtk_window_set_title (GTK_WINDOW (dialog), mount_name);
+ gtk_window_set_icon (GTK_WINDOW (dialog), pixbuf);
+ gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
+ g_object_unref (icon);
+ if (pixbuf) {
+ g_object_unref (pixbuf);
+ }
+ vbox = gtk_vbox_new (FALSE, 12);
+ gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
+
+ label = gtk_label_new (NULL);
+
+
+ /* Customize greeting for well-known x-content types */
+ if (strcmp (x_content_type, "x-content/audio-cdda") == 0) {
+ media_greeting = _("You have just inserted an Audio CD.");
+ } else if (strcmp (x_content_type, "x-content/audio-dvd") == 0) {
+ media_greeting = _("You have just inserted an Audio DVD.");
+ } else if (strcmp (x_content_type, "x-content/video-dvd") == 0) {
+ media_greeting = _("You have just inserted a Video DVD.");
+ } else if (strcmp (x_content_type, "x-content/video-vcd") == 0) {
+ media_greeting = _("You have just inserted a Video CD.");
+ } else if (strcmp (x_content_type, "x-content/video-svcd") == 0) {
+ media_greeting = _("You have just inserted a Super Video CD.");
+ } else if (strcmp (x_content_type, "x-content/blank-cd") == 0) {
+ media_greeting = _("You have just inserted a blank CD.");
+ } else if (strcmp (x_content_type, "x-content/blank-dvd") == 0) {
+ media_greeting = _("You have just inserted a blank DVD.");
+ } else if (strcmp (x_content_type, "x-content/blank-cd") == 0) {
+ media_greeting = _("You have just inserted a blank Blu-Ray disc.");
+ } else if (strcmp (x_content_type, "x-content/blank-cd") == 0) {
+ media_greeting = _("You have just inserted a blank HD DVD.");
+ } else if (strcmp (x_content_type, "x-content/image-photocd") == 0) {
+ media_greeting = _("You have just inserted a Photo CD.");
+ } else if (strcmp (x_content_type, "x-content/image-picturecd") == 0) {
+ media_greeting = _("You have just inserted a Picture CD.");
+ } else if (strcmp (x_content_type, "x-content/image-dcf") == 0) {
+ media_greeting = _("You have just inserted a medium with digital photos.");
+ } else if (strcmp (x_content_type, "x-content/audio-player") == 0) {
+ media_greeting = _("You have just inserted a digital audio player.");
+ } else if (g_content_type_is_a (x_content_type, "x-content/software")) {
+ media_greeting = _("You have just inserted a medium with software intended to be
automatically started.");
+ } else {
+ /* fallback to generic greeting */
+ media_greeting = _("You have just inserted a medium.");
+ }
+ markup = g_strdup_printf ("<big><b>%s %s</b></big>", media_greeting, _("Choose what application to
launch."));
+ gtk_label_set_markup (GTK_LABEL (label), markup);
+ g_free (markup);
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
+
+ label = gtk_label_new (NULL);
+ content_description = g_content_type_get_description (x_content_type);
+ markup = g_strdup_printf (_("Select how to open \"%s\" and whether to perform this action in the
future for other media of type \"%s\"."), mount_name, content_description);
+ g_free (content_description);
+ gtk_label_set_markup (GTK_LABEL (label), markup);
+ g_free (markup);
+ gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+ gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
+
+ data = g_new0 (AutorunDialogData, 1);
+ data->dialog = dialog;
+ data->mount = g_object_ref (mount);
+ data->remember = !pref_ask;
+ data->selected_ignore = pref_ignore;
+ data->x_content_type = g_strdup (x_content_type);
+ data->selected_app = g_app_info_get_default_for_type (x_content_type, FALSE);
+ data->open_window_func = open_window_func;
+ data->user_data = user_data;
+
+ combo_box = gtk_app_chooser_button_new (x_content_type);
+ prepare_combo_box (combo_box, data);
+ g_signal_connect (G_OBJECT (combo_box),
+ "key-press-event",
+ G_CALLBACK (combo_box_enter_ok),
+ dialog);
+
+ gtk_box_pack_start (GTK_BOX (vbox), combo_box, TRUE, TRUE, 0);
+
+ always_check_button = gtk_check_button_new_with_mnemonic (_("_Always perform this action"));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (always_check_button), data->remember);
+ g_signal_connect (G_OBJECT (always_check_button),
+ "toggled",
+ G_CALLBACK (autorun_always_toggled),
+ data);
+ gtk_box_pack_start (GTK_BOX (vbox), always_check_button, TRUE, TRUE, 0);
+
+ gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL);
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+
+ if (g_mount_can_eject (mount)) {
+ GtkWidget *eject_image;
+ eject_button = gtk_button_new_with_mnemonic (_("_Eject"));
+ eject_image = gtk_image_new_from_icon_name ("media-eject", GTK_ICON_SIZE_BUTTON);
+ gtk_button_set_image (GTK_BUTTON (eject_button), eject_image);
+ data->should_eject = TRUE;
+ } else {
+ eject_button = gtk_button_new_with_mnemonic (_("_Unmount"));
+ data->should_eject = FALSE;
+ }
+ gtk_dialog_add_action_widget (GTK_DIALOG (dialog), eject_button, AUTORUN_DIALOG_RESPONSE_EJECT);
+ gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (gtk_dialog_get_action_area (GTK_DIALOG
(dialog))), eject_button, TRUE);
+
+ /* show the dialog */
+ gtk_widget_show_all (dialog);
+
+ g_signal_connect (G_OBJECT (dialog),
+ "response",
+ G_CALLBACK (autorun_dialog_response),
+ data);
+
+ g_signal_connect (G_OBJECT (data->mount),
+ "unmounted",
+ G_CALLBACK (autorun_dialog_mount_unmounted),
+ data);
+
+out:
+ g_free (mount_name);
+ return ret;
+}
+
+typedef struct {
+ GMount *mount;
+ GsdAutorunOpenWindow open_window_func;
+ gpointer user_data;
+ GSettings *settings;
+} AutorunData;
+
+static void
+autorun_guessed_content_type_callback (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *error;
+ char **guessed_content_type;
+ AutorunData *data = user_data;
+ gboolean open_folder;
+
+ open_folder = FALSE;
+
+ error = NULL;
+ guessed_content_type = g_mount_guess_content_type_finish (G_MOUNT (source_object), res, &error);
+ g_object_set_data_full (source_object,
+ "gsd-content-type-cache",
+ g_strdupv (guessed_content_type),
+ (GDestroyNotify)g_strfreev);
+ if (error != NULL) {
+ g_warning ("Unable to guess content type for mount: %s", error->message);
+ g_error_free (error);
+ } else {
+ if (guessed_content_type != NULL && g_strv_length (guessed_content_type) > 0) {
+ int n;
+ for (n = 0; guessed_content_type[n] != NULL; n++) {
+ if (do_autorun_for_content_type (data->mount, guessed_content_type[n],
+ data->open_window_func, data->user_data)) {
+ open_folder = TRUE;
+ }
+ }
+ g_strfreev (guessed_content_type);
+ } else {
+ if (g_settings_get_boolean (data->settings, "automount-open")) {
+ open_folder = TRUE;
+ }
+ }
+ }
+
+ /* only open the folder once.. */
+ if (open_folder && data->open_window_func != NULL) {
+ data->open_window_func (data->mount, data->user_data);
+ }
+
+ g_object_unref (data->mount);
+ g_object_unref (data->settings);
+ g_free (data);
+}
+
+void
+gsd_autorun (GMount *mount,
+ GSettings *settings,
+ GsdAutorunOpenWindow open_window_func,
+ gpointer user_data)
+{
+ AutorunData *data;
+
+ if (!should_autorun_mount (mount) ||
+ g_settings_get_boolean (settings, "autorun-never")) {
+ return;
+ }
+
+ data = g_new0 (AutorunData, 1);
+ data->mount = g_object_ref (mount);
+ data->open_window_func = open_window_func;
+ data->user_data = user_data;
+ data->settings = g_object_ref (settings);
+
+ g_mount_guess_content_type (mount,
+ FALSE,
+ NULL,
+ autorun_guessed_content_type_callback,
+ data);
+}
+
+static gboolean
+remove_allow_volume (gpointer data)
+{
+ GVolume *volume = data;
+
+ g_object_set_data (G_OBJECT (volume), "gsd-allow-autorun", NULL);
+ return FALSE;
+}
+
+void
+gsd_allow_autorun_for_volume (GVolume *volume)
+{
+ g_object_set_data (G_OBJECT (volume), "gsd-allow-autorun", GINT_TO_POINTER (1));
+}
+
+#define INHIBIT_AUTORUN_SECONDS 10
+
+void
+gsd_allow_autorun_for_volume_finish (GVolume *volume)
+{
+ if (g_object_get_data (G_OBJECT (volume), "gsd-allow-autorun") != NULL) {
+ g_timeout_add_seconds_full (0,
+ INHIBIT_AUTORUN_SECONDS,
+ remove_allow_volume,
+ g_object_ref (volume),
+ g_object_unref);
+ }
+}
+
+static gboolean
+should_skip_native_mount_root (GFile *root)
+{
+ char *path;
+ gboolean should_skip;
+
+ /* skip any mounts in hidden directory hierarchies */
+ path = g_file_get_path (root);
+ should_skip = strstr (path, "/.") != NULL;
+ g_free (path);
+
+ return should_skip;
+}
+
+static gboolean
+should_autorun_mount (GMount *mount)
+{
+ GFile *root;
+ GVolume *enclosing_volume;
+ gboolean ignore_autorun;
+
+ ignore_autorun = TRUE;
+ enclosing_volume = g_mount_get_volume (mount);
+ if (enclosing_volume != NULL) {
+ if (g_object_get_data (G_OBJECT (enclosing_volume), "gsd-allow-autorun") != NULL) {
+ ignore_autorun = FALSE;
+ g_object_set_data (G_OBJECT (enclosing_volume), "gsd-allow-autorun", NULL);
+ }
+ }
+
+ if (ignore_autorun) {
+ if (enclosing_volume != NULL) {
+ g_object_unref (enclosing_volume);
+ }
+ return FALSE;
+ }
+
+ root = g_mount_get_root (mount);
+
+ /* only do autorun on local files or files where g_volume_should_automount() returns TRUE */
+ ignore_autorun = TRUE;
+ if ((g_file_is_native (root) && !should_skip_native_mount_root (root)) ||
+ (enclosing_volume != NULL && g_volume_should_automount (enclosing_volume))) {
+ ignore_autorun = FALSE;
+ }
+ if (enclosing_volume != NULL) {
+ g_object_unref (enclosing_volume);
+ }
+ g_object_unref (root);
+
+ return !ignore_autorun;
+}
diff --git a/gnome-flashback/libautomount-manager/gsd-autorun.h
b/gnome-flashback/libautomount-manager/gsd-autorun.h
new file mode 100644
index 0000000..85044be
--- /dev/null
+++ b/gnome-flashback/libautomount-manager/gsd-autorun.h
@@ -0,0 +1,53 @@
+/*
+ * gsd-automount.h:helpers for automounting hotplugged volumes
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * Nautilus 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: David Zeuthen <davidz redhat com>
+ * Cosimo Cecchi <cosimoc redhat com>
+ */
+
+/* TODO:
+ *
+ * - unmount all the media we've automounted on shutdown
+ * - finish x-content / * types
+ * - finalize the semi-spec
+ * - add probing/sniffing code
+ * - implement missing features
+ * - "Open Folder when mounted"
+ * - Autorun spec (e.g. $ROOT/.autostart)
+ *
+ */
+
+#ifndef __GSD_AUTORUN_H__
+#define __GSD_AUTORUN_H__
+
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+
+typedef void (*GsdAutorunOpenWindow) (GMount *mount,
+ gpointer user_data);
+
+void gsd_autorun (GMount *mount,
+ GSettings *settings,
+ GsdAutorunOpenWindow open_window_func,
+ gpointer user_data);
+
+void gsd_allow_autorun_for_volume (GVolume *volume);
+void gsd_allow_autorun_for_volume_finish (GVolume *volume);
+
+#endif /* __GSD_AUTORUN_H__ */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index c89a15b..0dcf7c7 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -10,6 +10,8 @@ data/gnome-flashback-metacity.session.in
data/org.gnome.gnome-flashback.gschema.xml.in.in
gnome-flashback/libend-session-dialog/flashback-inhibit-dialog.c
[type: gettext/glade]gnome-flashback/libend-session-dialog/flashback-inhibit-dialog.ui
+gnome-flashback/libautomount-manager/gsd-automount-manager.c
+gnome-flashback/libautomount-manager/gsd-autorun.c
gnome-flashback/libsound-applet/gvc-applet.c
gnome-flashback/libsound-applet/gvc-channel-bar.c
gnome-flashback/libsound-applet/gvc-stream-status-icon.c
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]