We need to integrate closely with the desktop environment of the user in several cases. Some examples are disabling auto-mounting when auto-usbredir is active (rhbz#812972), and disabling the screensaver when fullscreen (fdo#34793). Unfortuntely these kinds of things require desktop environment specific handling. Therefor this patch introduces a desktop-integration helper class, which is to server as a container for all sort of desktop environment specific functions. For now it just supports disabling automounting under Gnome-3, another patch extending it to also support disabling automounting under Gnome-2 is in the pipeline. Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx> --- configure.ac | 20 +++++ gtk/Makefile.am | 2 + gtk/desktop-integration.c | 196 +++++++++++++++++++++++++++++++++++++++++++++ gtk/desktop-integration.h | 64 +++++++++++++++ gtk/spice-session-priv.h | 2 + gtk/spice-session.c | 1 + 6 files changed, 285 insertions(+) create mode 100644 gtk/desktop-integration.c create mode 100644 gtk/desktop-integration.h diff --git a/configure.ac b/configure.ac index 09129b7..ade3649 100644 --- a/configure.ac +++ b/configure.ac @@ -566,6 +566,26 @@ fi AM_CONDITIONAL(WITH_PYTHON, [test "$WITH_PYTHON" = "yes"]) + +AC_ARG_ENABLE([gsettings], + AS_HELP_STRING([--enable-gsettings=@<:@auto/yes/no@:>@], + [Enable gsettings/gnome3 support for disabling automount @<:@default=auto@:>@]), + [], + [enable_gsettings="auto"]) + +if test "x$enable_gsettings" != "xno"; then + PKG_CHECK_MODULES([GSETTINGS], [glib-2.0 >= 2.26], + [have_gsettings=yes], + [have_gsettings=no]) + if test "x$enable_gsettings" = "xyes" && test "x$have_gsettings" = "xno"; then + AC_MSG_ERROR([GSettings support explicitly requested, but some required packages are not available]) + fi + + if test "x$have_gsettings" = "xyes"; then + AC_DEFINE(USE_GSETTINGS, [1], [Define if supporting gsettings]) + fi +fi + dnl =========================================================================== dnl check compiler flags diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 0327d65..c146601 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -226,6 +226,8 @@ libspice_client_glib_2_0_la_SOURCES = \ channel-smartcard.c \ channel-usbredir.c \ channel-usbredir-priv.h \ + desktop-integration.c \ + desktop-integration.h \ smartcard-manager.c \ smartcard-manager-priv.h \ usb-device-manager.c \ diff --git a/gtk/desktop-integration.c b/gtk/desktop-integration.c new file mode 100644 index 0000000..d948179 --- /dev/null +++ b/gtk/desktop-integration.c @@ -0,0 +1,196 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + Red Hat Authors: + Hans de Goede <hdegoede@xxxxxxxxxx> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "config.h" + +#include <glib-object.h> +#include <glib/gi18n.h> +#include "glib-compat.h" +#include "spice-session-priv.h" +#include "desktop-integration.h" + +/* ------------------------------------------------------------------ */ +/* gobject glue */ + +#define SPICE_DESKTOP_INTEGRATION_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), SPICE_TYPE_DESKTOP_INTEGRATION, SpiceDesktopIntegrationPrivate)) + +struct _SpiceDesktopIntegrationPrivate { +#ifdef USE_GSETTINGS + struct { + GSettings *media_hdl; + gboolean initial_automount; + gboolean current_automount; + } gnome3; +#else + gint dummy; +#endif +}; + +G_DEFINE_TYPE(SpiceDesktopIntegration, spice_desktop_integration, G_TYPE_OBJECT); + +/* ------------------------------------------------------------------ */ +/* Gnome3 specific code */ + +#ifdef USE_GSETTINGS +static void gnome3_integration_init(SpiceDesktopIntegration *self) +{ + SpiceDesktopIntegrationPrivate *priv = self->priv; + const gchar * const *schemas; + static gsize initial_automount = 0; + + schemas = g_settings_list_schemas(); + while (*schemas) { + if (strcmp(*schemas, "org.gnome.desktop.media-handling") == 0) + break; + schemas++; + } + + if (*schemas == NULL) + return; + + self->priv->gnome3.media_hdl = g_settings_new(*schemas); + if (g_once_init_enter(&initial_automount)) { + gsize init; + if (g_settings_get_boolean(self->priv->gnome3.media_hdl, "automount")) + init = 1; + else + init = -1; + g_once_init_leave(&initial_automount, init); + } + priv->gnome3.initial_automount = (initial_automount == 1) ? TRUE : FALSE; + priv->gnome3.current_automount = priv->gnome3.initial_automount; +} + +static void gnome3_integration_finalize(SpiceDesktopIntegration *self) +{ + g_clear_object(&self->priv->gnome3.media_hdl); +} + +static void gnome3_integration_disable_automount(SpiceDesktopIntegration *self) +{ + SpiceDesktopIntegrationPrivate *priv = self->priv; + + if (priv->gnome3.current_automount) { + if (g_settings_set_boolean(priv->gnome3.media_hdl, "automount", FALSE)) { + g_settings_sync(); + priv->gnome3.current_automount = FALSE; + } + } +} + +static void gnome3_integration_restore_automount(SpiceDesktopIntegration *self) +{ + SpiceDesktopIntegrationPrivate *priv = self->priv; + + if (priv->gnome3.current_automount != priv->gnome3.initial_automount) { + if (g_settings_set_boolean(priv->gnome3.media_hdl, "automount", + priv->gnome3.initial_automount)) { + priv->gnome3.current_automount = priv->gnome3.initial_automount; + } + } +} + +#endif + +/* ------------------------------------------------------------------ */ +/* gobject glue */ + +static void spice_desktop_integration_init(SpiceDesktopIntegration *self) +{ + SpiceDesktopIntegrationPrivate *priv; + + priv = SPICE_DESKTOP_INTEGRATION_GET_PRIVATE(self); + self->priv = priv; + +#ifdef USE_GSETTINGS + gnome3_integration_init(self); +#endif +} + +static void spice_desktop_integration_dispose(GObject *gobject) +{ + SpiceDesktopIntegration *self = SPICE_DESKTOP_INTEGRATION(gobject); + + spice_desktop_integration_restore_automount(self); + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(spice_desktop_integration_parent_class)->dispose) + G_OBJECT_CLASS(spice_desktop_integration_parent_class)->dispose(gobject); +} + +static void spice_desktop_integration_finalize(GObject *gobject) +{ + SpiceDesktopIntegration *self = SPICE_DESKTOP_INTEGRATION(gobject); + +#ifdef USE_GSETTINGS + gnome3_integration_finalize(self); +#endif + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(spice_desktop_integration_parent_class)->finalize) + G_OBJECT_CLASS(spice_desktop_integration_parent_class)->finalize(gobject); +} + +static void spice_desktop_integration_class_init(SpiceDesktopIntegrationClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->dispose = spice_desktop_integration_dispose; + gobject_class->finalize = spice_desktop_integration_finalize; + + g_type_class_add_private(klass, sizeof(SpiceDesktopIntegrationPrivate)); +} + +/* ------------------------------------------------------------------ */ +/* public methods */ + +SpiceDesktopIntegration *spice_desktop_integration_get(SpiceSession *session) +{ + SpiceDesktopIntegration *self; + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + + g_return_val_if_fail(session != NULL, NULL); + + g_static_mutex_lock(&mutex); + self = session->priv->desktop_integration; + if (self == NULL) { + self = g_object_new(SPICE_TYPE_DESKTOP_INTEGRATION, NULL); + session->priv->desktop_integration = self; + } + g_static_mutex_unlock(&mutex); + + return self; +} + +void spice_desktop_integration_disable_automount(SpiceDesktopIntegration *self) +{ +#ifdef USE_GSETTINGS + gnome3_integration_disable_automount(self); +#endif +} + +void spice_desktop_integration_restore_automount(SpiceDesktopIntegration *self) +{ +#ifdef USE_GSETTINGS + gnome3_integration_restore_automount(self); +#endif +} diff --git a/gtk/desktop-integration.h b/gtk/desktop-integration.h new file mode 100644 index 0000000..6780310 --- /dev/null +++ b/gtk/desktop-integration.h @@ -0,0 +1,64 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2012 Red Hat, Inc. + + Red Hat Authors: + Hans de Goede <hdegoede@xxxxxxxxxx> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +#ifndef __SPICE_DESKTOP_INTEGRATION_H__ +#define __SPICE_DESKTOP_INTEGRATION_H__ + +#include "spice-client.h" + +G_BEGIN_DECLS + +#define SPICE_TYPE_DESKTOP_INTEGRATION (spice_desktop_integration_get_type ()) +#define SPICE_DESKTOP_INTEGRATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SPICE_TYPE_DESKTOP_INTEGRATION, SpiceDesktopIntegration)) +#define SPICE_DESKTOP_INTEGRATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SPICE_TYPE_DESKTOP_INTEGRATION, SpiceDesktopIntegrationClass)) +#define SPICE_IS_DESKTOP_INTEGRATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SPICE_TYPE_DESKTOP_INTEGRATION)) +#define SPICE_IS_DESKTOP_INTEGRATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SPICE_TYPE_DESKTOP_INTEGRATION)) +#define SPICE_DESKTOP_INTEGRATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SPICE_TYPE_DESKTOP_INTEGRATION, SpiceDesktopIntegrationClass)) + +typedef struct _SpiceDesktopIntegration SpiceDesktopIntegration; +typedef struct _SpiceDesktopIntegrationClass SpiceDesktopIntegrationClass; +typedef struct _SpiceDesktopIntegrationPrivate SpiceDesktopIntegrationPrivate; + +/* + * SpiceDesktopIntegration offers helper-functions to do desktop environment + * and/or platform specific tasks like disabling automount, disabling the + * screen-saver, etc. SpiceDesktopIntegration is for internal spice-gtk usage + * only! + */ +struct _SpiceDesktopIntegration +{ + GObject parent; + + SpiceDesktopIntegrationPrivate *priv; +}; + +struct _SpiceDesktopIntegrationClass +{ + GObjectClass parent_class; +}; + +GType spice_desktop_integration_get_type(void); +SpiceDesktopIntegration *spice_desktop_integration_get(SpiceSession *session); +void spice_desktop_integration_disable_automount(SpiceDesktopIntegration *); +void spice_desktop_integration_restore_automount(SpiceDesktopIntegration *); + +G_END_DECLS + +#endif /* __SPICE_DESKTOP_INTEGRATION_H__ */ diff --git a/gtk/spice-session-priv.h b/gtk/spice-session-priv.h index 5cef264..c24ef8e 100644 --- a/gtk/spice-session-priv.h +++ b/gtk/spice-session-priv.h @@ -20,6 +20,7 @@ #include <glib.h> #include <gio/gio.h> +#include "desktop-integration.h" #include "spice-session.h" #include "spice-gtk-session.h" #include "spice-channel-cache.h" @@ -97,6 +98,7 @@ struct _SpiceSessionPrivate { /* associated objects */ SpiceAudio *audio_manager; + SpiceDesktopIntegration *desktop_integration; SpiceGtkSession *gtk_session; SpiceUsbDeviceManager *usb_manager; }; diff --git a/gtk/spice-session.c b/gtk/spice-session.c index fface67..995b2ed 100644 --- a/gtk/spice-session.c +++ b/gtk/spice-session.c @@ -155,6 +155,7 @@ spice_session_dispose(GObject *gobject) } g_clear_object(&s->audio_manager); + g_clear_object(&s->desktop_integration); g_clear_object(&s->gtk_session); g_clear_object(&s->usb_manager); -- 1.7.10.2 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel