]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkmountoperation.c
label: Fix memleak
[~andy/gtk] / gtk / gtkmountoperation.c
index ffa66568664a451a31be845fba5cc54466fba9ac..ed9178ae07c582bc0b0a07706816eedf57e75f4e 100644 (file)
@@ -13,9 +13,7 @@
  * 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, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
 #include <string.h>
 
 #include "gtkmountoperationprivate.h"
-#include "gtkalignment.h"
 #include "gtkbox.h"
+#include "gtkdbusgenerated.h"
 #include "gtkentry.h"
-#include "gtkhbox.h"
+#include "gtkbox.h"
 #include "gtkintl.h"
 #include "gtklabel.h"
-#include "gtkvbox.h"
 #include "gtkmessagedialog.h"
-#include "gtkmisc.h"
 #include "gtkmountoperation.h"
 #include "gtkprivate.h"
 #include "gtkradiobutton.h"
 #include "gtkstock.h"
-#include "gtktable.h"
+#include "gtkgrid.h"
 #include "gtkwindow.h"
 #include "gtktreeview.h"
 #include "gtktreeselection.h"
@@ -54,6 +50,8 @@
 #include "gtkimagemenuitem.h"
 #include "gtkmain.h"
 
+#include <glib/gprintf.h>
+
 /**
  * SECTION:filesystem
  * @short_description: Functions for working with GIO
@@ -120,12 +118,18 @@ struct _GtkMountOperationPrivate {
   GtkDialog *dialog;
   GdkScreen *screen;
 
+  /* bus proxy */
+  _GtkMountOperationHandler *handler;
+  GCancellable *cancellable;
+  gboolean handler_showing;
+
   /* for the ask-password dialog */
-  GtkWidget *entry_container;
+  GtkWidget *grid;
   GtkWidget *username_entry;
   GtkWidget *domain_entry;
   GtkWidget *password_entry;
   GtkWidget *anonymous_toggle;
+  GList *user_widgets;
 
   GAskPasswordFlags ask_flags;
   GPasswordSave     password_save;
@@ -181,9 +185,25 @@ gtk_mount_operation_class_init (GtkMountOperationClass *klass)
 static void
 gtk_mount_operation_init (GtkMountOperation *operation)
 {
+  gchar *name_owner;
+
   operation->priv = G_TYPE_INSTANCE_GET_PRIVATE (operation,
                                                  GTK_TYPE_MOUNT_OPERATION,
                                                  GtkMountOperationPrivate);
+
+  operation->priv->handler =
+    _gtk_mount_operation_handler_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                         G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+                                                         "org.gtk.MountOperationHandler",
+                                                         "/org/gtk/MountOperationHandler",
+                                                         NULL, NULL);
+  name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (operation->priv->handler));
+  if (!name_owner)
+    g_clear_object (&operation->priv->handler);
+  g_free (name_owner);
+
+  if (operation->priv->handler)
+    g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (operation->priv->handler), G_MAXINT);
 }
 
 static void
@@ -192,12 +212,18 @@ gtk_mount_operation_finalize (GObject *object)
   GtkMountOperation *operation = GTK_MOUNT_OPERATION (object);
   GtkMountOperationPrivate *priv = operation->priv;
 
+  if (priv->user_widgets)
+    g_list_free (priv->user_widgets);
+
   if (priv->parent_window)
     g_object_unref (priv->parent_window);
 
   if (priv->screen)
     g_object_unref (priv->screen);
 
+  if (priv->handler)
+    g_object_unref (priv->handler);
+
   G_OBJECT_CLASS (gtk_mount_operation_parent_class)->finalize (object);
 }
 
@@ -242,7 +268,7 @@ gtk_mount_operation_get_property (GObject    *object,
       break;
 
     case PROP_IS_SHOWING:
-      g_value_set_boolean (value, priv->dialog != NULL);
+      g_value_set_boolean (value, priv->dialog != NULL || priv->handler_showing);
       break;
 
     case PROP_SCREEN:
@@ -255,6 +281,21 @@ gtk_mount_operation_get_property (GObject    *object,
     }
 }
 
+static void
+gtk_mount_operation_proxy_finish (GtkMountOperation     *op,
+                                  GMountOperationResult  result)
+{
+  _gtk_mount_operation_handler_call_close (op->priv->handler, NULL, NULL, NULL);
+
+  op->priv->handler_showing = FALSE;
+  g_object_notify (G_OBJECT (op), "is-showing");
+
+  g_mount_operation_reply (G_MOUNT_OPERATION (op), result);
+
+  /* drop the reference acquired when calling the proxy method */
+  g_object_unref (op);
+}
+
 static void
 remember_button_toggled (GtkToggleButton   *button,
                          GtkMountOperation *operation)
@@ -367,6 +408,7 @@ pw_dialog_anonymous_toggled (GtkWidget         *widget,
 {
   GtkMountOperationPrivate *priv = operation->priv;
   gboolean is_valid;
+  GList *l;
 
   priv->anonymous = widget == priv->anonymous_toggle;
 
@@ -375,7 +417,11 @@ pw_dialog_anonymous_toggled (GtkWidget         *widget,
   else
     is_valid = pw_dialog_input_is_valid (operation);
 
-  gtk_widget_set_sensitive (priv->entry_container, priv->anonymous == FALSE);
+  for (l = priv->user_widgets; l != NULL; l = l->next)
+    {
+      gtk_widget_set_sensitive (GTK_WIDGET (l->data), !priv->anonymous);
+    }
+
   gtk_dialog_set_response_sensitive (GTK_DIALOG (priv->dialog),
                                      GTK_RESPONSE_OK,
                                      is_valid);
@@ -408,29 +454,31 @@ pw_dialog_cycle_focus (GtkWidget         *widget,
 }
 
 static GtkWidget *
-table_add_entry (GtkWidget  *table,
-                 int         row,
-                 const char *label_text,
-                 const char *value,
-                 gpointer    user_data)
+table_add_entry (GtkMountOperation *operation,
+                 int                row,
+                 const char        *label_text,
+                 const char        *value,
+                 gpointer           user_data)
 {
   GtkWidget *entry;
   GtkWidget *label;
 
   label = gtk_label_new_with_mnemonic (label_text);
-  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_widget_set_halign (label, GTK_ALIGN_END);
+  gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
+  gtk_widget_set_hexpand (label, FALSE);
+  operation->priv->user_widgets = g_list_prepend (operation->priv->user_widgets, label);
 
   entry = gtk_entry_new ();
+  gtk_widget_set_hexpand (entry, TRUE);
 
   if (value)
     gtk_entry_set_text (GTK_ENTRY (entry), value);
 
-  gtk_table_attach (GTK_TABLE (table), label,
-                    0, 1, row, row + 1,
-                    GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
-  gtk_table_attach_defaults (GTK_TABLE (table), entry,
-                             1, 2, row, row + 1);
+  gtk_grid_attach (GTK_GRID (operation->priv->grid), label, 0, row, 1, 1);
+  gtk_grid_attach (GTK_GRID (operation->priv->grid), entry, 1, row, 1, 1);
   gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
+  operation->priv->user_widgets = g_list_prepend (operation->priv->user_widgets, entry);
 
   g_signal_connect (entry, "changed",
                     G_CALLBACK (pw_dialog_verify_input), user_data);
@@ -442,31 +490,27 @@ table_add_entry (GtkWidget  *table,
 }
 
 static void
-gtk_mount_operation_ask_password (GMountOperation   *mount_op,
-                                  const char        *message,
-                                  const char        *default_user,
-                                  const char        *default_domain,
-                                  GAskPasswordFlags  flags)
+gtk_mount_operation_ask_password_do_gtk (GtkMountOperation *operation,
+                                         const gchar       *message,
+                                         const gchar       *default_user,
+                                         const gchar       *default_domain)
 {
-  GtkMountOperation *operation;
   GtkMountOperationPrivate *priv;
   GtkWidget *widget;
   GtkDialog *dialog;
   GtkWindow *window;
-  GtkWidget *entry_container;
-  GtkWidget *hbox, *main_vbox, *vbox, *icon;
-  GtkWidget *table;
-  GtkWidget *message_label;
+  GtkWidget *hbox, *main_vbox, *icon;
+  GtkWidget *grid;
+  GtkWidget *label;
   GtkWidget *content_area, *action_area;
   gboolean   can_anonymous;
   guint      rows;
+  gchar *primary;
   const gchar *secondary;
+  PangoAttrList *attrs;
 
-  operation = GTK_MOUNT_OPERATION (mount_op);
   priv = operation->priv;
 
-  priv->ask_flags = flags;
-
   widget = gtk_dialog_new ();
   dialog = GTK_DIALOG (widget);
   window = GTK_WINDOW (widget);
@@ -505,7 +549,8 @@ gtk_mount_operation_ask_password (GMountOperation   *mount_op,
   icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION,
                                    GTK_ICON_SIZE_DIALOG);
 
-  gtk_misc_set_alignment (GTK_MISC (icon), 0.5, 0.0);
+  gtk_widget_set_halign (icon, GTK_ALIGN_CENTER);
+  gtk_widget_set_valign (icon, GTK_ALIGN_START);
   gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
 
   main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 18);
@@ -514,35 +559,45 @@ gtk_mount_operation_ask_password (GMountOperation   *mount_op,
   secondary = strstr (message, "\n");
   if (secondary != NULL)
     {
-      gchar *s;
-      gchar *primary;
-
       primary = g_strndup (message, secondary - message + 1);
-      s = g_strdup_printf ("<big><b>%s</b></big>%s", primary, secondary);
-
-      message_label = gtk_label_new (NULL);
-      gtk_label_set_markup (GTK_LABEL (message_label), s);
-      gtk_misc_set_alignment (GTK_MISC (message_label), 0.0, 0.5);
-      gtk_label_set_line_wrap (GTK_LABEL (message_label), TRUE);
-      gtk_box_pack_start (GTK_BOX (main_vbox), GTK_WIDGET (message_label),
-                          FALSE, TRUE, 0);
-
-      g_free (s);
-      g_free (primary);
     }
   else
     {
-      message_label = gtk_label_new (message);
-      gtk_misc_set_alignment (GTK_MISC (message_label), 0.0, 0.5);
-      gtk_label_set_line_wrap (GTK_LABEL (message_label), TRUE);
-      gtk_box_pack_start (GTK_BOX (main_vbox), GTK_WIDGET (message_label),
+      primary = g_strdup (message);
+    }
+
+  label = gtk_label_new (primary);
+  gtk_widget_set_halign (label, GTK_ALIGN_START);
+  gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
+  gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+  gtk_box_pack_start (GTK_BOX (main_vbox), GTK_WIDGET (label),
+                      FALSE, TRUE, 0);
+  g_free (primary);
+  attrs = pango_attr_list_new ();
+  pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
+  gtk_label_set_attributes (GTK_LABEL (label), attrs);
+  pango_attr_list_unref (attrs);
+
+  if (secondary != NULL)
+    {
+      label = gtk_label_new (secondary);
+      gtk_widget_set_halign (label, GTK_ALIGN_START);
+      gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
+      gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+      gtk_box_pack_start (GTK_BOX (main_vbox), GTK_WIDGET (label),
                           FALSE, FALSE, 0);
     }
 
-  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
-  gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0);
+  grid = gtk_grid_new ();
+  operation->priv->grid = grid;
+  gtk_grid_set_row_spacing (GTK_GRID (grid), 12);
+  gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
+  gtk_widget_set_margin_bottom (grid, 12);
+  gtk_box_pack_start (GTK_BOX (main_vbox), grid, FALSE, FALSE, 0);
+
+  can_anonymous = priv->ask_flags & G_ASK_PASSWORD_ANONYMOUS_SUPPORTED;
 
-  can_anonymous = flags & G_ASK_PASSWORD_ANONYMOUS_SUPPORTED;
+  rows = 0;
 
   priv->anonymous_toggle = NULL;
   if (can_anonymous)
@@ -551,11 +606,16 @@ gtk_mount_operation_ask_password (GMountOperation   *mount_op,
       GtkWidget *choice;
       GSList    *group;
 
-      anon_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
-      gtk_box_pack_start (GTK_BOX (vbox), anon_box,
-                          FALSE, FALSE, 0);
+      label = gtk_label_new (_("Connect As"));
+      gtk_widget_set_halign (label, GTK_ALIGN_END);
+      gtk_widget_set_valign (label, GTK_ALIGN_START);
+      gtk_widget_set_hexpand (label, FALSE);
+      gtk_grid_attach (GTK_GRID (grid), label, 0, rows, 1, 1);
+
+      anon_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+      gtk_grid_attach (GTK_GRID (grid), anon_box, 1, rows++, 1, 1);
 
-      choice = gtk_radio_button_new_with_mnemonic (NULL, _("Connect _anonymously"));
+      choice = gtk_radio_button_new_with_mnemonic (NULL, _("_Anonymous"));
       gtk_box_pack_start (GTK_BOX (anon_box),
                           choice,
                           FALSE, FALSE, 0);
@@ -564,7 +624,7 @@ gtk_mount_operation_ask_password (GMountOperation   *mount_op,
       priv->anonymous_toggle = choice;
 
       group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (choice));
-      choice = gtk_radio_button_new_with_mnemonic (group, _("Connect as u_ser:"));
+      choice = gtk_radio_button_new_with_mnemonic (group, _("Registered U_ser"));
       gtk_box_pack_start (GTK_BOX (anon_box),
                           choice,
                           FALSE, FALSE, 0);
@@ -572,65 +632,42 @@ gtk_mount_operation_ask_password (GMountOperation   *mount_op,
                         G_CALLBACK (pw_dialog_anonymous_toggled), operation);
     }
 
-  rows = 0;
-
-  if (flags & G_ASK_PASSWORD_NEED_PASSWORD)
-    rows++;
-
-  if (flags & G_ASK_PASSWORD_NEED_USERNAME)
-    rows++;
-
-  if (flags &G_ASK_PASSWORD_NEED_DOMAIN)
-    rows++;
-
-  /* The table that holds the entries */
-  entry_container = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
-
-  gtk_alignment_set_padding (GTK_ALIGNMENT (entry_container),
-                             0, 0, can_anonymous ? 12 : 0, 0);
-
-  gtk_box_pack_start (GTK_BOX (vbox), entry_container,
-                      FALSE, FALSE, 0);
-  priv->entry_container = entry_container;
-
-  table = gtk_table_new (rows, 2, FALSE);
-  gtk_table_set_col_spacings (GTK_TABLE (table), 12);
-  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
-  gtk_container_add (GTK_CONTAINER (entry_container), table);
-
-  rows = 0;
-
   priv->username_entry = NULL;
-  if (flags & G_ASK_PASSWORD_NEED_USERNAME)
-    priv->username_entry = table_add_entry (table, rows++, _("_Username:"),
+
+  if (priv->ask_flags & G_ASK_PASSWORD_NEED_USERNAME)
+    priv->username_entry = table_add_entry (operation, rows++, _("_Username"),
                                             default_user, operation);
 
   priv->domain_entry = NULL;
-  if (flags & G_ASK_PASSWORD_NEED_DOMAIN)
-    priv->domain_entry = table_add_entry (table, rows++, _("_Domain:"),
+  if (priv->ask_flags & G_ASK_PASSWORD_NEED_DOMAIN)
+    priv->domain_entry = table_add_entry (operation, rows++, _("_Domain"),
                                           default_domain, operation);
 
   priv->password_entry = NULL;
-  if (flags & G_ASK_PASSWORD_NEED_PASSWORD)
+  if (priv->ask_flags & G_ASK_PASSWORD_NEED_PASSWORD)
     {
-      priv->password_entry = table_add_entry (table, rows++, _("_Password:"),
+      priv->password_entry = table_add_entry (operation, rows++, _("_Password"),
                                               NULL, operation);
       gtk_entry_set_visibility (GTK_ENTRY (priv->password_entry), FALSE);
     }
 
-   if (flags & G_ASK_PASSWORD_SAVING_SUPPORTED)
+   if (priv->ask_flags & G_ASK_PASSWORD_SAVING_SUPPORTED)
     {
-      GtkWidget    *choice;
       GtkWidget    *remember_box;
+      GtkWidget    *choice;
       GSList       *group;
       GPasswordSave password_save;
 
-      remember_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
-      gtk_box_pack_start (GTK_BOX (vbox), remember_box,
-                          FALSE, FALSE, 0);
+      remember_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+      gtk_grid_attach (GTK_GRID (grid), remember_box, 0, rows++, 2, 1);
+      priv->user_widgets = g_list_prepend (priv->user_widgets, remember_box);
+
+      label = gtk_label_new ("");
+      gtk_container_add (GTK_CONTAINER (remember_box), label);
+
+      password_save = g_mount_operation_get_password_save (G_MOUNT_OPERATION (operation));
+      priv->password_save = password_save;
 
-      password_save = g_mount_operation_get_password_save (mount_op);
-      
       choice = gtk_radio_button_new_with_mnemonic (NULL, _("Forget password _immediately"));
       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (choice),
                                     password_save == G_PASSWORD_SAVE_NEVER);
@@ -689,6 +726,92 @@ gtk_mount_operation_ask_password (GMountOperation   *mount_op,
   g_object_ref (operation);
 }
 
+static void
+call_password_proxy_cb (GObject      *source,
+                        GAsyncResult *res,
+                        gpointer      user_data)
+{
+  _GtkMountOperationHandler *proxy = _GTK_MOUNT_OPERATION_HANDLER (source);
+  GMountOperation *op = user_data;
+  GMountOperationResult result;
+  GVariant *result_details;
+  GVariantIter iter;
+  const gchar *key;
+  GVariant *value;
+  GError *error = NULL;
+
+  if (!_gtk_mount_operation_handler_call_ask_password_finish (proxy,
+                                                              &result,
+                                                              &result_details,
+                                                              res,
+                                                              &error))
+    {
+      result = G_MOUNT_OPERATION_ABORTED;
+      g_warning ("Shell mount operation error: %s\n", error->message);
+      g_error_free (error);
+      goto out;
+    }
+
+  g_variant_iter_init (&iter, result_details);
+  while (g_variant_iter_loop (&iter, "{&sv}", &key, &value))
+    {
+      if (strcmp (key, "password") == 0)
+        g_mount_operation_set_password (op, g_variant_get_string (value, NULL));
+      else if (strcmp (key, "password_save") == 0)
+        g_mount_operation_set_password_save (op, g_variant_get_uint32 (value));
+    }
+
+ out:
+  gtk_mount_operation_proxy_finish (GTK_MOUNT_OPERATION (op), result);
+}
+
+static void
+gtk_mount_operation_ask_password_do_proxy (GtkMountOperation *operation,
+                                           const char        *message,
+                                           const char        *default_user,
+                                           const char        *default_domain)
+{
+  gchar id[255];
+  g_sprintf(id, "GtkMountOperation%p", operation);
+
+  operation->priv->handler_showing = TRUE;
+  g_object_notify (G_OBJECT (operation), "is-showing");
+
+  /* keep a ref to the operation while the handler is showing */
+  g_object_ref (operation);
+
+  _gtk_mount_operation_handler_call_ask_password (operation->priv->handler, id,
+                                                  message, "drive-harddisk",
+                                                  default_user, default_domain,
+                                                  operation->priv->ask_flags, NULL,
+                                                  call_password_proxy_cb, operation);
+}
+
+static void
+gtk_mount_operation_ask_password (GMountOperation   *mount_op,
+                                  const char        *message,
+                                  const char        *default_user,
+                                  const char        *default_domain,
+                                  GAskPasswordFlags  flags)
+{
+  GtkMountOperation *operation;
+  GtkMountOperationPrivate *priv;
+  gboolean use_gtk;
+
+  operation = GTK_MOUNT_OPERATION (mount_op);
+  priv = operation->priv;
+  priv->ask_flags = flags;
+
+  use_gtk = (operation->priv->handler == NULL) ||
+    (priv->ask_flags & G_ASK_PASSWORD_NEED_DOMAIN) ||
+    (priv->ask_flags & G_ASK_PASSWORD_NEED_USERNAME);
+
+  if (use_gtk)
+    gtk_mount_operation_ask_password_do_gtk (operation, message, default_user, default_domain);
+  else
+    gtk_mount_operation_ask_password_do_proxy (operation, message, default_user, default_domain);
+}
+
 static void
 question_dialog_button_clicked (GtkDialog       *dialog,
                                 gint             button_number,
@@ -715,9 +838,9 @@ question_dialog_button_clicked (GtkDialog       *dialog,
 }
 
 static void
-gtk_mount_operation_ask_question (GMountOperation *op,
-                                  const char      *message,
-                                  const char      *choices[])
+gtk_mount_operation_ask_question_do_gtk (GtkMountOperation *op,
+                                         const char        *message,
+                                         const char        *choices[])
 {
   GtkMountOperationPrivate *priv;
   GtkWidget  *dialog;
@@ -729,7 +852,7 @@ gtk_mount_operation_ask_question (GMountOperation *op,
   g_return_if_fail (message != NULL);
   g_return_if_fail (choices != NULL);
 
-  priv = GTK_MOUNT_OPERATION (op)->priv;
+  priv = op->priv;
 
   primary = strstr (message, "\n");
   if (primary)
@@ -770,6 +893,80 @@ gtk_mount_operation_ask_question (GMountOperation *op,
   g_object_ref (op);
 }
 
+static void
+call_question_proxy_cb (GObject      *source,
+                        GAsyncResult *res,
+                        gpointer      user_data)
+{
+  _GtkMountOperationHandler *proxy = _GTK_MOUNT_OPERATION_HANDLER (source);
+  GMountOperation *op = user_data;
+  GMountOperationResult result;
+  GVariant *result_details;
+  GVariantIter iter;
+  const gchar *key;
+  GVariant *value;
+  GError *error = NULL;
+
+  if (!_gtk_mount_operation_handler_call_ask_question_finish (proxy,
+                                                              &result,
+                                                              &result_details,
+                                                              res,
+                                                              &error))
+    {
+      result = G_MOUNT_OPERATION_ABORTED;
+      g_warning ("Shell mount operation error: %s\n", error->message);
+      g_error_free (error);
+      goto out;
+    }
+
+  g_variant_iter_init (&iter, result_details);
+  while (g_variant_iter_loop (&iter, "{&sv}", &key, &value))
+    {
+      if (strcmp (key, "choice") == 0)
+        g_mount_operation_set_choice (op, g_variant_get_int32 (value));
+    }
+ out:
+  gtk_mount_operation_proxy_finish (GTK_MOUNT_OPERATION (op), result);
+}
+
+static void
+gtk_mount_operation_ask_question_do_proxy (GtkMountOperation *operation,
+                                           const char        *message,
+                                           const char        *choices[])
+{
+  gchar id[255];
+  g_sprintf(id, "GtkMountOperation%p", operation);
+
+  operation->priv->handler_showing = TRUE;
+  g_object_notify (G_OBJECT (operation), "is-showing");
+
+  /* keep a ref to the operation while the handler is showing */
+  g_object_ref (operation);
+
+  _gtk_mount_operation_handler_call_ask_question (operation->priv->handler, id,
+                                                  message, "drive-harddisk",
+                                                  choices, NULL,
+                                                  call_question_proxy_cb, operation);
+}
+
+static void
+gtk_mount_operation_ask_question (GMountOperation *op,
+                                  const char      *message,
+                                  const char      *choices[])
+{
+  GtkMountOperation *operation;
+  gboolean use_gtk;
+
+  operation = GTK_MOUNT_OPERATION (op);
+  use_gtk = (operation->priv->handler == NULL);
+
+  if (use_gtk)
+    gtk_mount_operation_ask_question_do_gtk (operation, message, choices);
+  else
+    gtk_mount_operation_ask_question_do_proxy (operation, message, choices);
+}
+
 static void
 show_processes_button_clicked (GtkDialog       *dialog,
                                gint             button_number,
@@ -1173,8 +1370,7 @@ on_button_press_event_for_process_tree_view (GtkWidget      *widget,
 
   ret = FALSE;
 
-  /* Ignore double-clicks and triple-clicks */
-  if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
+  if (gdk_event_triggers_context_menu ((GdkEvent *) event))
     {
       ret = do_popup_menu_for_process_tree_view (widget, event, op);
     }
@@ -1183,7 +1379,7 @@ on_button_press_event_for_process_tree_view (GtkWidget      *widget,
 }
 
 static GtkWidget *
-create_show_processes_dialog (GMountOperation *op,
+create_show_processes_dialog (GtkMountOperation *op,
                               const char      *message,
                               const char      *choices[])
 {
@@ -1202,7 +1398,7 @@ create_show_processes_dialog (GMountOperation *op,
   GtkListStore *list_store;
   gchar *s;
 
-  priv = GTK_MOUNT_OPERATION (op)->priv;
+  priv = op->priv;
 
   primary = strstr (message, "\n");
   if (primary)
@@ -1315,10 +1511,77 @@ create_show_processes_dialog (GMountOperation *op,
 }
 
 static void
-gtk_mount_operation_show_processes (GMountOperation *op,
-                                    const char      *message,
-                                    GArray          *processes,
-                                    const char      *choices[])
+call_processes_proxy_cb (GObject     *source,
+                        GAsyncResult *res,
+                        gpointer      user_data)
+{
+  _GtkMountOperationHandler *proxy = _GTK_MOUNT_OPERATION_HANDLER (source);
+  GMountOperation *op = user_data;
+  GMountOperationResult result;
+  GVariant *result_details;
+  GVariantIter iter;
+  const gchar *key;
+  GVariant *value;
+  GError *error = NULL;
+
+  if (!_gtk_mount_operation_handler_call_show_processes_finish (proxy,
+                                                                &result,
+                                                                &result_details,
+                                                                res,
+                                                                &error))
+    {
+      result = G_MOUNT_OPERATION_ABORTED;
+      g_warning ("Shell mount operation error: %s\n", error->message);
+      g_error_free (error);
+      goto out;
+    }
+
+  /* If the request was unhandled it means we called the method again;
+   * in this case, just return and wait for the next response.
+   */
+  if (result == G_MOUNT_OPERATION_UNHANDLED)
+    return;
+
+  g_variant_iter_init (&iter, result_details);
+  while (g_variant_iter_loop (&iter, "{&sv}", &key, &value))
+    {
+      if (strcmp (key, "choice") == 0)
+        g_mount_operation_set_choice (op, g_variant_get_int32 (value));
+    }
+
+ out:
+  gtk_mount_operation_proxy_finish (GTK_MOUNT_OPERATION (op), result);
+}
+
+static void
+gtk_mount_operation_show_processes_do_proxy (GtkMountOperation *operation,
+                                             const char        *message,
+                                             GArray            *processes,
+                                             const char        *choices[])
+{
+  gchar id[255];
+  g_sprintf(id, "GtkMountOperation%p", operation);
+
+  operation->priv->handler_showing = TRUE;
+  g_object_notify (G_OBJECT (operation), "is-showing");
+
+  /* keep a ref to the operation while the handler is showing */
+  g_object_ref (operation);
+
+  _gtk_mount_operation_handler_call_show_processes (operation->priv->handler, id,
+                                                    message, "drive-harddisk",
+                                                    g_variant_new_fixed_array (G_VARIANT_TYPE_INT32,
+                                                                               processes->data, processes->len,
+                                                                               sizeof (GPid)),
+                                                    choices, NULL,
+                                                    call_processes_proxy_cb, operation);
+}
+
+static void
+gtk_mount_operation_show_processes_do_gtk (GtkMountOperation *op,
+                                           const char        *message,
+                                           GArray            *processes,
+                                           const char        *choices[])
 {
   GtkMountOperationPrivate *priv;
   GtkWidget *dialog = NULL;
@@ -1328,7 +1591,7 @@ gtk_mount_operation_show_processes (GMountOperation *op,
   g_return_if_fail (processes != NULL);
   g_return_if_fail (choices != NULL);
 
-  priv = GTK_MOUNT_OPERATION (op)->priv;
+  priv = op->priv;
 
   if (priv->process_list_store == NULL)
     {
@@ -1338,7 +1601,7 @@ gtk_mount_operation_show_processes (GMountOperation *op,
 
   /* otherwise, we're showing the dialog, assume messages+choices hasn't changed */
 
-  update_process_list_store (GTK_MOUNT_OPERATION (op),
+  update_process_list_store (op,
                              priv->process_list_store,
                              processes);
 
@@ -1348,6 +1611,26 @@ gtk_mount_operation_show_processes (GMountOperation *op,
     }
 }
 
+
+static void
+gtk_mount_operation_show_processes (GMountOperation *op,
+                                    const char      *message,
+                                    GArray          *processes,
+                                    const char      *choices[])
+{
+
+  GtkMountOperation *operation;
+  gboolean use_gtk;
+
+  operation = GTK_MOUNT_OPERATION (op);
+  use_gtk = (operation->priv->handler == NULL);
+
+  if (use_gtk)
+    gtk_mount_operation_show_processes_do_gtk (operation, message, processes, choices);
+  else
+    gtk_mount_operation_show_processes_do_proxy (operation, message, processes, choices);
+}
+
 static void
 gtk_mount_operation_aborted (GMountOperation *op)
 {
@@ -1362,6 +1645,14 @@ gtk_mount_operation_aborted (GMountOperation *op)
       g_object_notify (G_OBJECT (op), "is-showing");
       g_object_unref (op);
     }
+
+  if (priv->handler != NULL)
+    {
+      _gtk_mount_operation_handler_call_close (priv->handler, NULL, NULL, NULL);
+
+      priv->handler_showing = FALSE;
+      g_object_notify (G_OBJECT (op), "is-showing");
+    }
 }
 
 /**