mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-11-01 08:52:18 +01:00 
			
		
		
		
	GDBus: Add an example of a GDBusProxy subclass
This commit is contained in:
		| @@ -218,6 +218,61 @@ on_proxy_appeared (GDBusConnection *connection, | ||||
|       proxy asynchronously, and only calls your callback when the proxy | ||||
|       is ready for use. | ||||
|     </para> | ||||
|  | ||||
|     <para> | ||||
|       For an example of a #GDBusProxy-derived class that wraps a D-Bus | ||||
|       interface in a type-safe way, see <xref | ||||
|       linkend="gdbus-example-proxy-subclass"/>. The comparison is as | ||||
|       follows: | ||||
|       <table id="gdbus-example-type-safe-proxy"> | ||||
|         <title>Wrapping the org.freedesktop.Accounts.User D-Bus interface in the AccountUser GObject type</title> | ||||
|         <tgroup cols="2"> | ||||
|           <thead> | ||||
|             <row><entry>D-Bus concept</entry><entry>GObject concept</entry></row> | ||||
|           </thead> | ||||
|           <tbody> | ||||
|             <row> | ||||
|               <entry>AutomaticLogin property</entry> | ||||
|               <entry> | ||||
|                 <para><literal>AccountsUser:automatic-login</literal> GObject property</para> | ||||
|                 <para>C getter: accounts_user_get_automatic_login()</para> | ||||
|                 <para>Watch changes via the <literal>notify::automatic-login</literal> signal</para> | ||||
|               </entry> | ||||
|             </row> | ||||
|             <row> | ||||
|               <entry>RealName property</entry> | ||||
|               <entry> | ||||
|                 <para><literal>AccountsUser:real-name</literal> GObject property</para> | ||||
|                 <para>C getter: accounts_user_get_real_name()</para> | ||||
|                 <para>Watch changes via the <literal>notify::real-name signal</literal></para> | ||||
|               </entry> | ||||
|             </row> | ||||
|             <row> | ||||
|               <entry>UserName property</entry> | ||||
|               <entry> | ||||
|                 <para><literal>AccountsUser:user-name</literal> GObject property</para> | ||||
|                 <para>C getter: accounts_user_get_user_name()</para> | ||||
|                 <para>Watch changes via the <literal>notify::user-name</literal> signal</para> | ||||
|               </entry> | ||||
|             </row> | ||||
|             <row> | ||||
|               <entry>Changed signal</entry> | ||||
|               <entry> | ||||
|                 <para><literal>AccountsUser::changed</literal> GObject signal</para> | ||||
|                 <para>Watch via e.g. g_signal_connect()</para> | ||||
|               </entry> | ||||
|             </row> | ||||
|             <row> | ||||
|               <entry>Frobnicate method</entry> | ||||
|               <entry> | ||||
|                 <para>Use accounts_user_frobnicate() + accounts_user_frobnicate_finish() or accounts_user_frobnicate_sync() to invoke</para> | ||||
|               </entry> | ||||
|             </row> | ||||
|           </tbody> | ||||
|         </tgroup> | ||||
|       </table> | ||||
|     </para> | ||||
|     <example id="gdbus-example-proxy-subclass"><title>GDBusProxy subclass example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-proxy-subclass.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example> | ||||
|   </section> | ||||
|  | ||||
|   <section> | ||||
|   | ||||
| @@ -101,8 +101,6 @@ | ||||
|  * | ||||
|  *  - Consistent timeout handling (25s vs 30s?) | ||||
|  * | ||||
|  *  - GDBusProxy subclass example | ||||
|  * | ||||
|  *  - Update GDBusAuthObserver (s/deny/authorize/) | ||||
|  */ | ||||
|  | ||||
|   | ||||
| @@ -64,6 +64,7 @@ SAMPLE_PROGS = 				\ | ||||
| 	gdbus-example-server		\ | ||||
| 	gdbus-example-subtree		\ | ||||
| 	gdbus-example-peer		\ | ||||
| 	gdbus-example-proxy-subclass	\ | ||||
| 	$(NULL) | ||||
|  | ||||
|  | ||||
| @@ -230,6 +231,9 @@ gdbus_example_subtree_LDADD   = $(progs_ldadd) | ||||
| gdbus_example_peer_SOURCES = gdbus-example-peer.c | ||||
| gdbus_example_peer_LDADD   = $(progs_ldadd) | ||||
|  | ||||
| gdbus_example_proxy_subclass_SOURCES = gdbus-example-proxy-subclass.c | ||||
| gdbus_example_proxy_subclass_LDADD   = $(progs_ldadd) | ||||
|  | ||||
| EXTRA_DIST += \ | ||||
| 	socket-common.c						\ | ||||
| 	org.gtk.test.gschema					\ | ||||
|   | ||||
							
								
								
									
										443
									
								
								gio/tests/gdbus-example-proxy-subclass.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										443
									
								
								gio/tests/gdbus-example-proxy-subclass.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,443 @@ | ||||
|  | ||||
| #include <gio/gio.h> | ||||
|  | ||||
| /* ---------------------------------------------------------------------------------------------------- */ | ||||
| /* The D-Bus interface definition we want to create a GDBusProxy-derived type for: */ | ||||
| /* ---------------------------------------------------------------------------------------------------- */ | ||||
|  | ||||
| static const gchar introspection_xml[] = | ||||
|   "<node>" | ||||
|   "  <interface name='org.freedesktop.Accounts.User'>" | ||||
|   "    <method name='Frobnicate'>" | ||||
|   "      <arg name='flux' type='s' direction='in'/>" | ||||
|   "      <arg name='baz' type='s' direction='in'/>" | ||||
|   "      <arg name='result' type='s' direction='out'/>" | ||||
|   "    </method>" | ||||
|   "    <signal name='Changed'/>" | ||||
|   "    <property name='AutomaticLogin' type='b' access='readwrite'/>" | ||||
|   "    <property name='RealName' type='s' access='read'/>" | ||||
|   "    <property name='UserName' type='s' access='read'/>" | ||||
|   "  </interface>" | ||||
|   "</node>"; | ||||
|  | ||||
| /* ---------------------------------------------------------------------------------------------------- */ | ||||
| /* Definition of the AccountsUser type */ | ||||
| /* ---------------------------------------------------------------------------------------------------- */ | ||||
|  | ||||
| #define ACCOUNTS_TYPE_USER         (accounts_user_get_type ()) | ||||
| #define ACCOUNTS_USER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), ACCOUNTS_TYPE_USER, AccountsUser)) | ||||
| #define ACCOUNTS_USER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), ACCOUNTS_TYPE_USER, AccountsUserClass)) | ||||
| #define ACCOUNTS_USER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), ACCOUNTS_TYPE_USER, AccountsUserClass)) | ||||
| #define ACCOUNTS_IS_USER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), ACCOUNTS_TYPE_USER)) | ||||
| #define ACCOUNTS_IS_USER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), ACCOUNTS_TYPE_USER)) | ||||
|  | ||||
| typedef struct _AccountsUser        AccountsUser; | ||||
| typedef struct _AccountsUserClass   AccountsUserClass; | ||||
| typedef struct _AccountsUserPrivate AccountsUserPrivate; | ||||
|  | ||||
| struct _AccountsUser | ||||
| { | ||||
|   /*< private >*/ | ||||
|   GDBusProxy parent_instance; | ||||
|   AccountsUserPrivate *priv; | ||||
| }; | ||||
|  | ||||
| struct _AccountsUserClass | ||||
| { | ||||
|   /*< private >*/ | ||||
|   GDBusProxyClass parent_class; | ||||
|   void (*changed) (AccountsUser *user); | ||||
| }; | ||||
|  | ||||
| GType        accounts_user_get_type            (void) G_GNUC_CONST; | ||||
|  | ||||
| const gchar *accounts_user_get_user_name       (AccountsUser        *user); | ||||
| const gchar *accounts_user_get_real_name       (AccountsUser        *user); | ||||
| gboolean     accounts_user_get_automatic_login (AccountsUser        *user); | ||||
|  | ||||
| void         accounts_user_frobnicate          (AccountsUser        *user, | ||||
|                                                 const gchar         *flux, | ||||
|                                                 gint                 baz, | ||||
|                                                 GCancellable        *cancellable, | ||||
|                                                 GAsyncReadyCallback  callback, | ||||
|                                                 gpointer             user_data); | ||||
| gchar       *accounts_user_frobnicate_finish   (AccountsUser        *user, | ||||
|                                                 GAsyncResult        *res, | ||||
|                                                 GError             **error); | ||||
| gchar       *accounts_user_frobnicate_sync     (AccountsUser        *user, | ||||
|                                                 const gchar         *flux, | ||||
|                                                 gint                 baz, | ||||
|                                                 GCancellable        *cancellable, | ||||
|                                                 GError             **error); | ||||
|  | ||||
| /* ---------------------------------------------------------------------------------------------------- */ | ||||
| /* Implementation of the AccountsUser type */ | ||||
| /* ---------------------------------------------------------------------------------------------------- */ | ||||
|  | ||||
| /* A more efficient approach than parsing XML is to use const static | ||||
|  * GDBusInterfaceInfo, GDBusMethodInfo, ... structures | ||||
|  */ | ||||
| static GDBusInterfaceInfo * | ||||
| accounts_user_get_interface_info (void) | ||||
| { | ||||
|   static gsize has_info = 0; | ||||
|   static GDBusInterfaceInfo *info = NULL; | ||||
|   if (g_once_init_enter (&has_info)) | ||||
|     { | ||||
|       GDBusNodeInfo *introspection_data; | ||||
|       introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); | ||||
|       info = introspection_data->interfaces[0]; | ||||
|       g_once_init_leave (&has_info, 1); | ||||
|     } | ||||
|   return info; | ||||
| } | ||||
|  | ||||
| enum | ||||
| { | ||||
|   PROP_0, | ||||
|   PROP_USER_NAME, | ||||
|   PROP_REAL_NAME, | ||||
|   PROP_AUTOMATIC_LOGIN, | ||||
| }; | ||||
|  | ||||
| enum | ||||
| { | ||||
|   CHANGED_SIGNAL, | ||||
|   LAST_SIGNAL | ||||
| }; | ||||
|  | ||||
| static guint signals[LAST_SIGNAL] = {0}; | ||||
|  | ||||
| G_DEFINE_TYPE (AccountsUser, accounts_user, G_TYPE_DBUS_PROXY); | ||||
|  | ||||
| static void | ||||
| accounts_user_finalize (GObject *object) | ||||
| { | ||||
|   G_GNUC_UNUSED AccountsUser *user = ACCOUNTS_USER (object); | ||||
|  | ||||
|   if (G_OBJECT_CLASS (accounts_user_parent_class)->finalize != NULL) | ||||
|     G_OBJECT_CLASS (accounts_user_parent_class)->finalize (object); | ||||
| } | ||||
|  | ||||
| static void | ||||
| accounts_user_init (AccountsUser *user) | ||||
| { | ||||
|   /* Sets the expected interface */ | ||||
|   g_dbus_proxy_set_interface_info (G_DBUS_PROXY (user), accounts_user_get_interface_info ()); | ||||
| } | ||||
|  | ||||
| static void | ||||
| accounts_user_get_property (GObject    *object, | ||||
|                             guint       prop_id, | ||||
|                             GValue     *value, | ||||
|                             GParamSpec *pspec) | ||||
| { | ||||
|   AccountsUser *user = ACCOUNTS_USER (object); | ||||
|  | ||||
|   switch (prop_id) | ||||
|     { | ||||
|     case PROP_USER_NAME: | ||||
|       g_value_set_string (value, accounts_user_get_user_name (user)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_REAL_NAME: | ||||
|       g_value_set_string (value, accounts_user_get_real_name (user)); | ||||
|       break; | ||||
|  | ||||
|     case PROP_AUTOMATIC_LOGIN: | ||||
|       g_value_set_boolean (value, accounts_user_get_automatic_login (user)); | ||||
|       break; | ||||
|  | ||||
|     default: | ||||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| const gchar * | ||||
| accounts_user_get_user_name (AccountsUser *user) | ||||
| { | ||||
|   GVariant *value; | ||||
|   const gchar *ret; | ||||
|   g_return_val_if_fail (ACCOUNTS_IS_USER (user), NULL); | ||||
|   value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (user), "UserName", NULL); | ||||
|   ret = g_variant_get_string (value, NULL); | ||||
|   g_variant_unref (value); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| const gchar * | ||||
| accounts_user_get_real_name (AccountsUser *user) | ||||
| { | ||||
|   GVariant *value; | ||||
|   const gchar *ret; | ||||
|   g_return_val_if_fail (ACCOUNTS_IS_USER (user), NULL); | ||||
|   value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (user), "RealName", NULL); | ||||
|   ret = g_variant_get_string (value, NULL); | ||||
|   g_variant_unref (value); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| accounts_user_get_automatic_login (AccountsUser *user) | ||||
| { | ||||
|   GVariant *value; | ||||
|   gboolean ret; | ||||
|   g_return_val_if_fail (ACCOUNTS_IS_USER (user), FALSE); | ||||
|   value = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (user), "AutomaticLogin", NULL); | ||||
|   ret = g_variant_get_boolean (value); | ||||
|   g_variant_unref (value); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| static void | ||||
| accounts_user_g_signal (GDBusProxy   *proxy, | ||||
|                         const gchar  *sender_name, | ||||
|                         const gchar  *signal_name, | ||||
|                         GVariant     *parameters) | ||||
| { | ||||
|   AccountsUser *user = ACCOUNTS_USER (proxy); | ||||
|   if (g_strcmp0 (signal_name, "Changed") == 0) | ||||
|     g_signal_emit (user, signals[CHANGED_SIGNAL], 0); | ||||
| } | ||||
|  | ||||
| static void | ||||
| accounts_user_g_properties_changed (GDBusProxy *proxy, | ||||
|                                     GVariant   *changed_properties) | ||||
| { | ||||
|   AccountsUser *user = ACCOUNTS_USER (proxy); | ||||
|   GVariantIter *iter; | ||||
|   GVariant *item; | ||||
|  | ||||
|   g_variant_get (changed_properties, "a{sv}", &iter); | ||||
|   while ((item = g_variant_iter_next_value (iter)) != NULL) | ||||
|     { | ||||
|       const gchar *key; | ||||
|       g_variant_get (item, | ||||
|                      "{sv}", | ||||
|                      &key, | ||||
|                      NULL); | ||||
|       if (g_strcmp0 (key, "AutomaticLogin") == 0) | ||||
|         g_object_notify (G_OBJECT (user), "automatic-login"); | ||||
|       else if (g_strcmp0 (key, "RealName") == 0) | ||||
|         g_object_notify (G_OBJECT (user), "real-name"); | ||||
|       else if (g_strcmp0 (key, "UserName") == 0) | ||||
|         g_object_notify (G_OBJECT (user), "user-name"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| accounts_user_class_init (AccountsUserClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class; | ||||
|   GDBusProxyClass *proxy_class; | ||||
|  | ||||
|   gobject_class = G_OBJECT_CLASS (klass); | ||||
|   gobject_class->get_property = accounts_user_get_property; | ||||
|   gobject_class->finalize = accounts_user_finalize; | ||||
|  | ||||
|   proxy_class = G_DBUS_PROXY_CLASS (klass); | ||||
|   proxy_class->g_signal             = accounts_user_g_signal; | ||||
|   proxy_class->g_properties_changed = accounts_user_g_properties_changed; | ||||
|  | ||||
|   g_object_class_install_property (gobject_class, | ||||
|                                    PROP_USER_NAME, | ||||
|                                    g_param_spec_string ("user-name", | ||||
|                                                         "User Name", | ||||
|                                                         "The user name of the user", | ||||
|                                                         NULL, | ||||
|                                                         G_PARAM_READABLE | | ||||
|                                                         G_PARAM_STATIC_STRINGS)); | ||||
|  | ||||
|   g_object_class_install_property (gobject_class, | ||||
|                                    PROP_REAL_NAME, | ||||
|                                    g_param_spec_string ("real-name", | ||||
|                                                         "Real Name", | ||||
|                                                         "The real name of the user", | ||||
|                                                         NULL, | ||||
|                                                         G_PARAM_READABLE | | ||||
|                                                         G_PARAM_STATIC_STRINGS)); | ||||
|  | ||||
|   g_object_class_install_property (gobject_class, | ||||
|                                    PROP_AUTOMATIC_LOGIN, | ||||
|                                    g_param_spec_boolean ("automatic-login", | ||||
|                                                          "Automatic Login", | ||||
|                                                          "Whether the user is automatically logged in", | ||||
|                                                          FALSE, | ||||
|                                                          G_PARAM_READABLE | | ||||
|                                                          G_PARAM_STATIC_STRINGS)); | ||||
|  | ||||
|   signals[CHANGED_SIGNAL] = g_signal_new ("changed", | ||||
|                                           ACCOUNTS_TYPE_USER, | ||||
|                                           G_SIGNAL_RUN_LAST, | ||||
|                                           G_STRUCT_OFFSET (AccountsUserClass, changed), | ||||
|                                           NULL, | ||||
|                                           NULL, | ||||
|                                           g_cclosure_marshal_VOID__VOID, | ||||
|                                           G_TYPE_NONE, | ||||
|                                           0); | ||||
| } | ||||
|  | ||||
| gchar * | ||||
| accounts_user_frobnicate_sync (AccountsUser        *user, | ||||
|                                const gchar         *flux, | ||||
|                                gint                 baz, | ||||
|                                GCancellable        *cancellable, | ||||
|                                GError             **error) | ||||
| { | ||||
|   gchar *ret; | ||||
|   GVariant *value; | ||||
|  | ||||
|   g_return_val_if_fail (ACCOUNTS_IS_USER (user), NULL); | ||||
|  | ||||
|   ret = NULL; | ||||
|  | ||||
|   value = g_dbus_proxy_call_sync (G_DBUS_PROXY (user), | ||||
|                                   "Frobnicate", | ||||
|                                   g_variant_new ("(si)", | ||||
|                                                  flux, | ||||
|                                                  baz), | ||||
|                                   G_DBUS_CALL_FLAGS_NONE, | ||||
|                                   -1, | ||||
|                                   cancellable, | ||||
|                                   error); | ||||
|   if (value != NULL) | ||||
|     { | ||||
|       g_variant_get (value, "(s)", &ret); | ||||
|       ret = g_strdup (ret); | ||||
|       g_variant_unref (value); | ||||
|     } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| void | ||||
| accounts_user_frobnicate (AccountsUser        *user, | ||||
|                           const gchar         *flux, | ||||
|                           gint                 baz, | ||||
|                           GCancellable        *cancellable, | ||||
|                           GAsyncReadyCallback  callback, | ||||
|                           gpointer             user_data) | ||||
| { | ||||
|   g_return_if_fail (ACCOUNTS_IS_USER (user)); | ||||
|   g_dbus_proxy_call (G_DBUS_PROXY (user), | ||||
|                      "Frobnicate", | ||||
|                      g_variant_new ("(si)", | ||||
|                                     flux, | ||||
|                                     baz), | ||||
|                      G_DBUS_CALL_FLAGS_NONE, | ||||
|                      -1, | ||||
|                      cancellable, | ||||
|                      callback, | ||||
|                      user_data); | ||||
| } | ||||
|  | ||||
|  | ||||
| gchar * | ||||
| accounts_user_frobnicate_finish (AccountsUser        *user, | ||||
|                                  GAsyncResult        *res, | ||||
|                                  GError             **error) | ||||
| { | ||||
|   gchar *ret; | ||||
|   GVariant *value; | ||||
|  | ||||
|   ret = NULL; | ||||
|   value = g_dbus_proxy_call_finish (G_DBUS_PROXY (user), res, error); | ||||
|   if (value != NULL) | ||||
|     { | ||||
|       g_variant_get (value, "(s)", &ret); | ||||
|       ret = g_strdup (ret); | ||||
|       g_variant_unref (value); | ||||
|     } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| /* ---------------------------------------------------------------------------------------------------- */ | ||||
| /* Example usage of the AccountsUser type */ | ||||
| /* ---------------------------------------------------------------------------------------------------- */ | ||||
|  | ||||
| static void | ||||
| print_user (AccountsUser *user) | ||||
| { | ||||
|   g_print ("  user-name       = `%s'\n", accounts_user_get_user_name (user)); | ||||
|   g_print ("  real-name       = `%s'\n", accounts_user_get_real_name (user)); | ||||
|   g_print ("  automatic-login = %s\n", accounts_user_get_automatic_login (user) ? "true" : "false"); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_changed (AccountsUser *user, | ||||
|             gpointer      user_data) | ||||
| { | ||||
|   g_print ("+++ Received the AccountsUser::changed signal\n"); | ||||
|   print_user (user); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_notify (GObject    *object, | ||||
|            GParamSpec *pspec, | ||||
|            gpointer    user_data) | ||||
| { | ||||
|   AccountsUser *user = ACCOUNTS_USER (object); | ||||
|   g_print ("+++ Received the GObject::notify signal for property `%s'\n", | ||||
|            pspec->name); | ||||
|   print_user (user); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_proxy_appeared (GDBusConnection *connection, | ||||
|                    const gchar     *name, | ||||
|                    const gchar     *name_owner, | ||||
|                    GDBusProxy      *proxy, | ||||
|                    gpointer         user_data) | ||||
| { | ||||
|   AccountsUser *user = ACCOUNTS_USER (proxy); | ||||
|  | ||||
|   g_print ("+++ Acquired proxy for user\n"); | ||||
|   print_user (user); | ||||
|  | ||||
|   g_signal_connect (proxy, | ||||
|                     "notify", | ||||
|                     G_CALLBACK (on_notify), | ||||
|                     NULL); | ||||
|   g_signal_connect (user, | ||||
|                     "changed", | ||||
|                     G_CALLBACK (on_changed), | ||||
|                     NULL); | ||||
| } | ||||
|  | ||||
| static void | ||||
| on_proxy_vanished (GDBusConnection *connection, | ||||
|                    const gchar     *name, | ||||
|                    gpointer         user_data) | ||||
| { | ||||
|   g_print ("--- Cannot create proxy for user: no remote object\n"); | ||||
| } | ||||
|  | ||||
| /* ---------------------------------------------------------------------------------------------------- */ | ||||
|  | ||||
| gint | ||||
| main (gint argc, gchar *argv[]) | ||||
| { | ||||
|   guint watcher_id; | ||||
|   GMainLoop *loop; | ||||
|  | ||||
|   g_type_init (); | ||||
|  | ||||
|   watcher_id = g_bus_watch_proxy (G_BUS_TYPE_SYSTEM, | ||||
|                                   "org.freedesktop.Accounts", | ||||
|                                   G_BUS_NAME_WATCHER_FLAGS_AUTO_START, | ||||
|                                   "/org/freedesktop/Accounts/User500", | ||||
|                                   "org.freedesktop.Accounts.User", | ||||
|                                   ACCOUNTS_TYPE_USER, | ||||
|                                   G_DBUS_PROXY_FLAGS_NONE, | ||||
|                                   on_proxy_appeared, | ||||
|                                   on_proxy_vanished, | ||||
|                                   NULL, | ||||
|                                   NULL); | ||||
|  | ||||
|   loop = g_main_loop_new (NULL, FALSE); | ||||
|   g_main_loop_run (loop); | ||||
|   g_main_loop_unref (loop); | ||||
|   g_bus_unwatch_proxy (watcher_id); | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user