Commit 87aa3382 authored by Balló György's avatar Balló György 🇭🇺 Committed by Alberts Muktupāvels
Browse files

Add libautomount-manager

It was previously in gnome-settings-daemon.
parent a7a54573
......@@ -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
......
<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>
......
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 \
......
......@@ -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;
......
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
/* -*- 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)