[nautilus-actions] New BaseISession interface



commit 47e9f321f94b786b8d52393eb8665d2f286d4c07
Author: Pierre Wieser <pwieser trychlos org>
Date:   Mon Jan 9 23:32:48 2012 +0100

    New BaseISession interface

 ChangeLog                   |    6 +
 src/nact/Makefile.am        |    2 +
 src/nact/base-application.c |  120 ++++----------------
 src/nact/base-isession.c    |  263 +++++++++++++++++++++++++++++++++++++++++++
 src/nact/base-isession.h    |   68 +++++++++++
 5 files changed, 363 insertions(+), 96 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 72dfa41..37a9b5f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2012-01-09 Pierre Wieser <pwieser trychlos org>
 
+	* src/nact/base-isession.c:
+	* src/nact/base-isession.h: New BaseISession interface.
+
+	* src/nact/Makefile.am:
+	* src/nact/base-application.c (init_session_manager): Updated accordingly.
+
 	* src/nact/base-application.h: Update comments.
 
 	* src/nact/base-window.c:
diff --git a/src/nact/Makefile.am b/src/nact/Makefile.am
index 10397ba..da0d906 100644
--- a/src/nact/Makefile.am
+++ b/src/nact/Makefile.am
@@ -58,6 +58,8 @@ nautilus_actions_config_tool_SOURCES = \
 	base-dialog.h										\
 	base-gtk-utils.c									\
 	base-gtk-utils.h									\
+	base-isession.c										\
+	base-isession.h										\
 	base-iunique.c										\
 	base-iunique.h										\
 	base-keysyms.h										\
diff --git a/src/nact/base-application.c b/src/nact/base-application.c
index eb1f849..5a009b9 100644
--- a/src/nact/base-application.c
+++ b/src/nact/base-application.c
@@ -36,8 +36,8 @@
 #include <string.h>
 
 #include "base-application.h"
+#include "base-isession.h"
 #include "base-iunique.h"
-#include "egg-sm-client.h"
 
 /* private class data
  */
@@ -60,12 +60,6 @@ struct _BaseApplicationPrivate {
 	gchar        *icon_name;
 	gchar        *unique_app_name;
 	int           code;
-
-	/* internals
-	 */
-	EggSMClient  *sm_client;
-	gulong        sm_client_quit_handler_id;
-	gulong        sm_client_quit_requested_handler_id;
 };
 
 /* instance properties
@@ -89,6 +83,7 @@ static GObjectClass *st_parent_class = NULL;
 
 static GType          register_type( void );
 static void           class_init( BaseApplicationClass *klass );
+static void           isession_iface_init( BaseISessionInterface *iface, void *user_data );
 static void           iunique_iface_init( BaseIUniqueInterface *iface, void *user_data );
 static const gchar   *iunique_get_application_name( const BaseIUnique *instance );
 static void           instance_init( GTypeInstance *instance, gpointer klass );
@@ -103,19 +98,30 @@ static gboolean       init_gtk( BaseApplication *application );
 static gboolean       v_manage_options( BaseApplication *application );
 static gboolean       init_unique_manager( BaseApplication *application );
 static gboolean       init_session_manager( BaseApplication *application );
-static void           session_manager_client_quit_cb( EggSMClient *client, BaseApplication *application );
-static void           session_manager_client_quit_requested_cb( EggSMClient *client, BaseApplication *application );
 static gboolean       init_icon_name( BaseApplication *application );
 static gboolean       v_init_application( BaseApplication *application );
 static gboolean       v_create_windows( BaseApplication *application );
 
+/*
+ * the BaseISessionInterface interface is registered here because
+ * the interface requires its implementation to be of BaseApplication
+ * type. So we have to first register the type class before trying to
+ * register the type interface.
+ */
 GType
 base_application_get_type( void )
 {
 	static GType application_type = 0;
 
+	static const GInterfaceInfo isession_iface_info = {
+		( GInterfaceInitFunc ) isession_iface_init,
+		NULL,
+		NULL
+	};
+
 	if( !application_type ){
 		application_type = register_type();
+		g_type_add_interface_static( application_type, BASE_ISESSION_TYPE, &isession_iface_info );
 	}
 
 	return( application_type );
@@ -243,6 +249,14 @@ class_init( BaseApplicationClass *klass )
 }
 
 static void
+isession_iface_init( BaseISessionInterface *iface, void *user_data )
+{
+	static const gchar *thisfn = "base_application_isession_iface_init";
+
+	g_debug( "%s: iface=%p, user_data=%p", thisfn, ( void * ) iface, ( void * ) user_data );
+}
+
+static void
 iunique_iface_init( BaseIUniqueInterface *iface, void *user_data )
 {
 	static const gchar *thisfn = "base_application_iunique_iface_init";
@@ -402,20 +416,6 @@ instance_dispose( GObject *application )
 
 		self->private->dispose_has_run = TRUE;
 
-		if( self->private->sm_client_quit_handler_id &&
-			g_signal_handler_is_connected( self->private->sm_client, self->private->sm_client_quit_handler_id )){
-				g_signal_handler_disconnect( self->private->sm_client, self->private->sm_client_quit_handler_id  );
-		}
-
-		if( self->private->sm_client_quit_requested_handler_id &&
-			g_signal_handler_is_connected( self->private->sm_client, self->private->sm_client_quit_requested_handler_id )){
-				g_signal_handler_disconnect( self->private->sm_client, self->private->sm_client_quit_requested_handler_id  );
-		}
-
-		if( self->private->sm_client ){
-			g_object_unref( self->private->sm_client );
-		}
-
 		/* chain up to the parent class */
 		if( G_OBJECT_CLASS( st_parent_class )->dispose ){
 			G_OBJECT_CLASS( st_parent_class )->dispose( application );
@@ -661,87 +661,15 @@ static gboolean
 init_session_manager( BaseApplication *application )
 {
 	static const gchar *thisfn = "base_application_init_session_manager";
-	BaseApplicationPrivate *priv;
 
 	g_debug( "%s: application=%p", thisfn, ( void * ) application );
 
-	priv = application->private;
-
-	egg_sm_client_set_mode( EGG_SM_CLIENT_MODE_NO_RESTART );
-	priv->sm_client = egg_sm_client_get();
-	egg_sm_client_startup();
-	g_debug( "%s: sm_client=%p", thisfn, ( void * ) priv->sm_client );
-
-	priv->sm_client_quit_handler_id =
-			g_signal_connect(
-					priv->sm_client,
-					"quit-requested",
-					G_CALLBACK( session_manager_client_quit_requested_cb ),
-					application );
-
-	priv->sm_client_quit_requested_handler_id =
-			g_signal_connect(
-					priv->sm_client,
-					"quit",
-					G_CALLBACK( session_manager_client_quit_cb ),
-					application );
+	base_isession_init( BASE_ISESSION( application ));
 
 	return( TRUE );
 }
 
 /*
- * cleanly terminate the main window when exiting the session
- */
-static void
-session_manager_client_quit_cb( EggSMClient *client, BaseApplication *application )
-{
-	static const gchar *thisfn = "base_application_session_manager_client_quit_cb";
-
-	g_return_if_fail( BASE_IS_APPLICATION( application ));
-
-	if( !application->private->dispose_has_run ){
-
-		g_debug( "%s: client=%p, application=%p", thisfn, ( void * ) client, ( void * ) application );
-
-#if 0
-		if( application->private->main_window ){
-
-				g_return_if_fail( BASE_IS_WINDOW( application->private->main_window ));
-				g_object_unref( application->private->main_window );
-				application->private->main_window = NULL;
-		}
-#endif
-	}
-}
-
-/*
- * the session manager advertises us that the session is about to exit
- */
-static void
-session_manager_client_quit_requested_cb( EggSMClient *client, BaseApplication *application )
-{
-	static const gchar *thisfn = "base_application_session_manager_client_quit_requested_cb";
-	gboolean willing_to = TRUE;
-
-	g_return_if_fail( BASE_IS_APPLICATION( application ));
-
-	if( !application->private->dispose_has_run ){
-
-		g_debug( "%s: client=%p, application=%p", thisfn, ( void * ) client, ( void * ) application );
-
-#if 0
-		if( application->private->main_window ){
-
-				g_return_if_fail( BASE_IS_WINDOW( application->private->main_window ));
-				willing_to = base_window_is_willing_to_quit( application->private->main_window );
-		}
-#endif
-	}
-
-	egg_sm_client_will_quit( client, willing_to );
-}
-
-/*
  * From GTK+ Reference Manual:
  * Sets an icon to be used as fallback for windows that haven't had
  * gtk_window_set_icon_list() called on them from a named themed icon.
diff --git a/src/nact/base-isession.c b/src/nact/base-isession.c
new file mode 100644
index 0000000..1e5470c
--- /dev/null
+++ b/src/nact/base-isession.c
@@ -0,0 +1,263 @@
+/*
+ * Nautilus-Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009, 2010, 2011, 2012 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "base-application.h"
+#include "base-isession.h"
+#include "egg-sm-client.h"
+
+/* private interface data
+ */
+struct _BaseISessionInterfacePrivate {
+	void *empty;						/* so that gcc -pedantic is happy */
+};
+
+/* private properties, set against the instance
+ */
+typedef struct {
+	EggSMClient *sm_client;
+	gulong       sm_client_quit_handler_id;
+	gulong       sm_client_quit_requested_handler_id;
+}
+	ISessionStr;
+
+/* Above ISessionStr struct is set as a BaseISession pseudo-property
+ * of the instance.
+ */
+#define BASE_PROP_ISESSION				"base-prop-isession"
+
+static guint st_initializations = 0;	/* interface initialisation count */
+
+static GType        register_type( void );
+static void         interface_base_init( BaseISessionInterface *klass );
+static void         interface_base_finalize( BaseISessionInterface *klass );
+
+static void         on_instance_finalized( gpointer user_data, BaseISession *instance );
+static void         client_quit_requested_cb( EggSMClient *client, BaseISession *instance );
+static void         client_quit_cb( EggSMClient *client, BaseISession *instance );
+static ISessionStr *get_isession_str( BaseISession *instance );
+
+GType
+base_isession_get_type( void )
+{
+	static GType iface_type = 0;
+
+	if( !iface_type ){
+		iface_type = register_type();
+	}
+
+	return( iface_type );
+}
+
+static GType
+register_type( void )
+{
+	static const gchar *thisfn = "base_isession_register_type";
+	GType type;
+
+	static const GTypeInfo info = {
+		sizeof( BaseISessionInterface ),
+		( GBaseInitFunc ) interface_base_init,
+		( GBaseFinalizeFunc ) interface_base_finalize,
+		NULL,
+		NULL,
+		NULL,
+		0,
+		0,
+		NULL
+	};
+
+	g_debug( "%s", thisfn );
+
+	type = g_type_register_static( G_TYPE_INTERFACE, "BaseISession", &info, 0 );
+
+	g_type_interface_add_prerequisite( type, BASE_APPLICATION_TYPE );
+
+	return( type );
+}
+
+static void
+interface_base_init( BaseISessionInterface *klass )
+{
+	static const gchar *thisfn = "base_isession_interface_base_init";
+
+	if( !st_initializations ){
+
+		g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+		klass->private = g_new0( BaseISessionInterfacePrivate, 1 );
+	}
+
+	st_initializations += 1;
+}
+
+static void
+interface_base_finalize( BaseISessionInterface *klass )
+{
+	static const gchar *thisfn = "base_isession_interface_base_finalize";
+
+	st_initializations -= 1;
+
+	if( !st_initializations ){
+
+		g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+		g_free( klass->private );
+	}
+}
+
+void
+base_isession_init( BaseISession *instance )
+{
+	static const gchar *thisfn = "base_isession_init";
+	ISessionStr *str;
+
+	g_return_if_fail( BASE_IS_ISESSION( instance ));
+
+	g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+
+	str = get_isession_str( instance );
+
+	/* set a weak reference to be advertised when the instance is finalized
+	 */
+	g_object_weak_ref( G_OBJECT( instance ), ( GWeakNotify ) on_instance_finalized, NULL );
+
+	/* initialize the session manager
+	 */
+	egg_sm_client_set_mode( EGG_SM_CLIENT_MODE_NO_RESTART );
+	str->sm_client = egg_sm_client_get();
+	egg_sm_client_startup();
+	g_debug( "%s: sm_client=%p", thisfn, ( void * ) str->sm_client );
+
+	str->sm_client_quit_handler_id =
+			g_signal_connect(
+					str->sm_client,
+					"quit-requested",
+					G_CALLBACK( client_quit_requested_cb ),
+					instance );
+
+	str->sm_client_quit_requested_handler_id =
+			g_signal_connect(
+					str->sm_client,
+					"quit",
+					G_CALLBACK( client_quit_cb ),
+					instance );
+}
+
+static void
+on_instance_finalized( gpointer user_data, BaseISession *instance )
+{
+	static const gchar *thisfn = "base_isession_on_instance_finalized";
+	ISessionStr *str;
+
+	g_debug( "%s: instance=%p, user_data=%p", thisfn, ( void * ) instance, ( void * ) user_data );
+
+	str = get_isession_str( instance );
+
+	if( str->sm_client_quit_handler_id &&
+		g_signal_handler_is_connected( str->sm_client, str->sm_client_quit_handler_id )){
+			g_signal_handler_disconnect( str->sm_client, str->sm_client_quit_handler_id  );
+	}
+
+	if( str->sm_client_quit_requested_handler_id &&
+		g_signal_handler_is_connected( str->sm_client, str->sm_client_quit_requested_handler_id )){
+			g_signal_handler_disconnect( str->sm_client, str->sm_client_quit_requested_handler_id  );
+	}
+
+	if( str->sm_client ){
+		g_object_unref( str->sm_client );
+	}
+
+	g_free( str );
+}
+
+/*
+ * the session manager advertises us that the session is about to exit
+ */
+static void
+client_quit_requested_cb( EggSMClient *client, BaseISession *instance )
+{
+	static const gchar *thisfn = "base_isession_client_quit_requested_cb";
+	gboolean willing_to = TRUE;
+
+	g_return_if_fail( BASE_IS_ISESSION( instance ));
+
+	g_debug( "%s: client=%p, instance=%p", thisfn, ( void * ) client, ( void * ) instance );
+
+#if 0
+		if( application->private->main_window ){
+
+				g_return_if_fail( BASE_IS_WINDOW( application->private->main_window ));
+				willing_to = base_window_is_willing_to_quit( application->private->main_window );
+		}
+#endif
+
+	egg_sm_client_will_quit( client, willing_to );
+}
+
+/*
+ * cleanly terminate the main window when exiting the session
+ */
+static void
+client_quit_cb( EggSMClient *client, BaseISession *instance )
+{
+	static const gchar *thisfn = "base_isession_client_quit_cb";
+
+	g_return_if_fail( BASE_IS_ISESSION( instance ));
+
+	g_debug( "%s: client=%p, instance=%p", thisfn, ( void * ) client, ( void * ) instance );
+
+#if 0
+		if( application->private->main_window ){
+
+				g_return_if_fail( BASE_IS_WINDOW( application->private->main_window ));
+				g_object_unref( application->private->main_window );
+				application->private->main_window = NULL;
+		}
+#endif
+}
+
+static ISessionStr *
+get_isession_str( BaseISession *instance )
+{
+	ISessionStr *str;
+
+	str = ( ISessionStr * ) g_object_get_data( G_OBJECT( instance ), BASE_PROP_ISESSION );
+
+	if( !str ){
+		str = g_new0( ISessionStr, 1 );
+		g_object_set_data( G_OBJECT( instance ), BASE_PROP_ISESSION, str );
+	}
+
+	return( str );
+}
diff --git a/src/nact/base-isession.h b/src/nact/base-isession.h
new file mode 100644
index 0000000..874ce52
--- /dev/null
+++ b/src/nact/base-isession.h
@@ -0,0 +1,68 @@
+/*
+ * Nautilus-Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009, 2010, 2011, 2012 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 Library; see the file COPYING.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *   Frederic Ruaudel <grumz grumz net>
+ *   Rodrigo Moya <rodrigo gnome-db org>
+ *   Pierre Wieser <pwieser trychlos org>
+ *   ... and many others (see AUTHORS)
+ */
+
+#ifndef __BASE_ISESSION_H__
+#define __BASE_ISESSION_H__
+
+/**
+ * SECTION: base_isession
+ * @short_description: #BaseISession interface definition.
+ * @include: nact/base-isession.h
+ *
+ * This interface implements the features to make an application
+ * unique, i.e. cjheck that we run only one instance of it.
+ */
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define BASE_ISESSION_TYPE                      ( base_isession_get_type())
+#define BASE_ISESSION( object )                 ( G_TYPE_CHECK_INSTANCE_CAST( object, BASE_ISESSION_TYPE, BaseISession ))
+#define BASE_IS_ISESSION( object )              ( G_TYPE_CHECK_INSTANCE_TYPE( object, BASE_ISESSION_TYPE ))
+#define BASE_ISESSION_GET_INTERFACE( instance ) ( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), BASE_ISESSION_TYPE, BaseISessionInterface ))
+
+typedef struct _BaseISession                    BaseISession;
+typedef struct _BaseISessionInterfacePrivate    BaseISessionInterfacePrivate;
+
+typedef struct {
+	/*< private >*/
+	GTypeInterface                parent;
+	BaseISessionInterfacePrivate *private;
+}
+	BaseISessionInterface;
+
+GType    base_isession_get_type( void );
+
+void     base_isession_init    ( BaseISession *instance );
+
+G_END_DECLS
+
+#endif /* __BASE_ISESSION_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]