Ejemplo n.º 1
0
gboolean
gtk_file_chooser_native_portal_show (GtkFileChooserNative *self)
{
  FilechooserPortalData *data;
  GtkWindow *transient_for;
  GDBusConnection *connection;
  char *parent_window_str;
  GDBusMessage *message;
  GVariantBuilder opt_builder;
  GtkFileChooserAction action;
  gboolean multiple;
  const char *method_name;

  if (!gtk_should_use_portal ())
    return FALSE;

  connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
  if (connection == NULL)
    return FALSE;

  action = gtk_file_chooser_get_action (GTK_FILE_CHOOSER (self));
  multiple = gtk_file_chooser_get_select_multiple (GTK_FILE_CHOOSER (self));

  if (action == GTK_FILE_CHOOSER_ACTION_OPEN)
    method_name = "OpenFile";
  else if (action == GTK_FILE_CHOOSER_ACTION_SAVE)
    method_name = "SaveFile";
  else
    {
      g_warning ("GTK_FILE_CHOOSER_ACTION_%s is not supported by GtkFileChooserNativePortal", action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ? "SELECT_FOLDER" : "CREATE_FOLDER");
      return FALSE;
    }

  data = g_new0 (FilechooserPortalData, 1);
  data->self = g_object_ref (self);
  data->connection = connection;

  message = g_dbus_message_new_method_call ("org.freedesktop.portal.Desktop",
                                            "/org/freedesktop/portal/desktop",
                                            "org.freedesktop.portal.FileChooser",
                                            method_name);

  parent_window_str = NULL;
  transient_for = gtk_native_dialog_get_transient_for (GTK_NATIVE_DIALOG (self));
  if (transient_for != NULL && gtk_widget_is_visible (GTK_WIDGET (transient_for)))
    {
      GdkWindow *window = gtk_widget_get_window (GTK_WIDGET (transient_for));
#ifdef GDK_WINDOWING_X11
      if (GDK_IS_X11_WINDOW(window))
        parent_window_str = g_strdup_printf ("x11:%x", (guint32)gdk_x11_window_get_xid (window));
#endif
    }

  if (gtk_native_dialog_get_modal (GTK_NATIVE_DIALOG (self)))
    data->modal = TRUE;

  if (data->modal && transient_for != NULL)
    {
      data->grab_widget = gtk_invisible_new_for_screen (gtk_widget_get_screen (GTK_WIDGET (transient_for)));
      gtk_grab_add (GTK_WIDGET (data->grab_widget));
    }

  g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
  g_variant_builder_add (&opt_builder, "{sv}", "multiple",
                         g_variant_new_boolean (multiple));
  if (self->accept_label)
    g_variant_builder_add (&opt_builder, "{sv}", "accept_label",
                           g_variant_new_string (self->accept_label));
  if (self->cancel_label)
    g_variant_builder_add (&opt_builder, "{sv}", "cancel_label",
                           g_variant_new_string (self->cancel_label));
  g_variant_builder_add (&opt_builder, "{sv}", "modal",
                         g_variant_new_boolean (data->modal));
  g_variant_builder_add (&opt_builder, "{sv}", "filters", get_filters (GTK_FILE_CHOOSER (self)));
  if (GTK_FILE_CHOOSER_NATIVE (self)->current_name)
    g_variant_builder_add (&opt_builder, "{sv}", "current_name",
                           g_variant_new_string (GTK_FILE_CHOOSER_NATIVE (self)->current_name));
  if (GTK_FILE_CHOOSER_NATIVE (self)->current_folder)
    {
      gchar *path;

      path = g_file_get_path (GTK_FILE_CHOOSER_NATIVE (self)->current_folder);
      g_variant_builder_add (&opt_builder, "{sv}", "current_folder",
                             g_variant_new_bytestring (path));
      g_free (path);
    }
  if (GTK_FILE_CHOOSER_NATIVE (self)->current_file)
    {
      gchar *path;

      path = g_file_get_path (GTK_FILE_CHOOSER_NATIVE (self)->current_file);
      g_variant_builder_add (&opt_builder, "{sv}", "current_file",
                             g_variant_new_bytestring (path));
      g_free (path);
    }

  if (GTK_FILE_CHOOSER_NATIVE (self)->choices)
    g_variant_builder_add (&opt_builder, "{sv}", "choices",
                           serialize_choices (GTK_FILE_CHOOSER_NATIVE (self)));

  g_dbus_message_set_body (message,
                           g_variant_new ("(ss@a{sv})",
                                          parent_window_str ? parent_window_str : "",
                                          gtk_native_dialog_get_title (GTK_NATIVE_DIALOG (self)),
                                          g_variant_builder_end (&opt_builder)));
  g_free (parent_window_str);

  g_dbus_connection_send_message_with_reply (data->connection,
                                             message,
                                             G_DBUS_SEND_MESSAGE_FLAGS_NONE,
                                             G_MAXINT,
                                             NULL,
                                             NULL,
                                             open_file_msg_cb,
                                             data);

  g_object_unref (message);

  self->mode_data = data;
  return TRUE;
}
Ejemplo n.º 2
0
/**
 * fu_util_install_internal:
 **/
static gboolean
fu_util_install_internal (FuUtilPrivate *priv, const gchar *id,
			  const gchar *filename, GError **error)
{
	GVariant *body;
	GVariantBuilder builder;
	gint retval;
	gint fd;
	_cleanup_object_unref_ GDBusMessage *request = NULL;
	_cleanup_object_unref_ GUnixFDList *fd_list = NULL;

	/* set options */
	g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
	g_variant_builder_add (&builder, "{sv}",
			       "reason", g_variant_new_string ("user-action"));
	g_variant_builder_add (&builder, "{sv}",
			       "filename", g_variant_new_string (filename));
	if (priv->flags & FU_PROVIDER_UPDATE_FLAG_OFFLINE) {
		g_variant_builder_add (&builder, "{sv}",
				       "offline", g_variant_new_boolean (TRUE));
	}
	if (priv->flags & FU_PROVIDER_UPDATE_FLAG_ALLOW_OLDER) {
		g_variant_builder_add (&builder, "{sv}",
				       "allow-older", g_variant_new_boolean (TRUE));
	}
	if (priv->flags & FU_PROVIDER_UPDATE_FLAG_ALLOW_REINSTALL) {
		g_variant_builder_add (&builder, "{sv}",
				       "allow-reinstall", g_variant_new_boolean (TRUE));
	}

	/* open file */
	fd = open (filename, O_RDONLY);
	if (fd < 0) {
		g_set_error (error,
			     FWUPD_ERROR,
			     FWUPD_ERROR_INVALID_FILE,
			     "failed to open %s",
			     filename);
		return FALSE;
	}

	/* set out of band file descriptor */
	fd_list = g_unix_fd_list_new ();
	retval = g_unix_fd_list_append (fd_list, fd, NULL);
	g_assert (retval != -1);
	request = g_dbus_message_new_method_call (FWUPD_DBUS_SERVICE,
						  FWUPD_DBUS_PATH,
						  FWUPD_DBUS_INTERFACE,
						  "Install");
	g_dbus_message_set_unix_fd_list (request, fd_list);

	/* g_unix_fd_list_append did a dup() already */
	close (fd);

	/* send message */
	body = g_variant_new ("(sha{sv})", id, fd > -1 ? 0 : -1, &builder);
	g_dbus_message_set_body (request, body);
	g_dbus_connection_send_message_with_reply (priv->conn,
						   request,
						   G_DBUS_SEND_MESSAGE_FLAGS_NONE,
						   -1,
						   NULL,
						   NULL,
						   fu_util_update_cb,
						   priv);
	g_main_loop_run (priv->loop);
	if (priv->message == NULL) {
		g_dbus_error_strip_remote_error (priv->error);
		g_propagate_error (error, priv->error);
		return FALSE;
	}
	if (g_dbus_message_to_gerror (priv->message, error)) {
		g_dbus_error_strip_remote_error (*error);
		return FALSE;
	}
	/* TRANSLATORS: update completed, no errors */
	g_print ("%s\n", _("Done!"));
	return TRUE;
}
Ejemplo n.º 3
0
/**
 * fu_util_refresh_internal:
 **/
static gboolean
fu_util_refresh_internal (FuUtilPrivate *priv,
				  const gchar *data_fn,
				  const gchar *sig_fn,
				  GError **error)
{
	GVariant *body;
	gint fd;
	gint fd_sig;
	_cleanup_object_unref_ GDBusMessage *request = NULL;
	_cleanup_object_unref_ GUnixFDList *fd_list = NULL;

	/* open file */
	fd = open (data_fn, O_RDONLY);
	if (fd < 0) {
		g_set_error (error,
			     FWUPD_ERROR,
			     FWUPD_ERROR_INVALID_FILE,
			     "failed to open %s",
			     data_fn);
		return FALSE;
	}
	fd_sig = open (sig_fn, O_RDONLY);
	if (fd_sig < 0) {
		g_set_error (error,
			     FWUPD_ERROR,
			     FWUPD_ERROR_INVALID_FILE,
			     "failed to open %s",
			     sig_fn);
		return FALSE;
	}

	/* set out of band file descriptor */
	fd_list = g_unix_fd_list_new ();
	g_unix_fd_list_append (fd_list, fd, NULL);
	g_unix_fd_list_append (fd_list, fd_sig, NULL);
	request = g_dbus_message_new_method_call (FWUPD_DBUS_SERVICE,
						  FWUPD_DBUS_PATH,
						  FWUPD_DBUS_INTERFACE,
						  "UpdateMetadata");
	g_dbus_message_set_unix_fd_list (request, fd_list);

	/* g_unix_fd_list_append did a dup() already */
	close (fd);
	close (fd_sig);

	/* send message */
	body = g_variant_new ("(hh)", fd, fd_sig);
	g_dbus_message_set_body (request, body);
	g_dbus_connection_send_message_with_reply (priv->conn,
						   request,
						   G_DBUS_SEND_MESSAGE_FLAGS_NONE,
						   -1,
						   NULL,
						   NULL,
						   fu_util_update_cb,
						   priv);
	g_main_loop_run (priv->loop);
	if (priv->message == NULL) {
		g_dbus_error_strip_remote_error (priv->error);
		g_propagate_error (error, priv->error);
		return FALSE;
	}
	if (g_dbus_message_to_gerror (priv->message, error)) {
		g_dbus_error_strip_remote_error (*error);
		return FALSE;
	}
	return TRUE;
}
Ejemplo n.º 4
0
gboolean
eas_gdbus_call (struct eas_gdbus_client *client, const gchar *object,
		const gchar *interface, const gchar *method,
		EasProgressFn progress_fn, gpointer progress_data,
		const gchar *in_params, const gchar *out_params,
		GCancellable *cancellable, GError **error, ...)
{
	GDBusMessage *message;
	struct _eas_call_data call;
	GMainContext *ctxt;
	GVariant *v = NULL;
	va_list ap;
	gboolean success;
	guint cancel_handler_id;
	guint32 serial = 0;

	va_start (ap, error);

	message = g_dbus_message_new_method_call (EAS_SERVICE_NAME, object,
						  interface, method);

	v = g_variant_new_va (in_params, NULL, &ap);
	g_dbus_message_set_body (message, v);

	call.cancelled = FALSE;
	call.result = NULL;
	ctxt = g_main_context_new ();
	call.loop = g_main_loop_new (ctxt, FALSE);

	g_main_context_push_thread_default (ctxt);

	g_dbus_connection_send_message_with_reply (client->connection,
						   message,
						   G_DBUS_SEND_MESSAGE_FLAGS_NONE,
						   1000000,
						   &serial,
						   cancellable,
						   _call_done,
						   (gpointer) &call);
	g_object_unref (message);

	if (cancellable)
		cancel_handler_id = g_cancellable_connect (cancellable,
							  G_CALLBACK (_call_cancel),
							  (gpointer) &call, NULL);

	/* Ignore error; it's not the end of the world if progress info
	   is lost, and it should never happen anyway */
	if (progress_fn)
		eas_client_add_progress_info_to_table (client, serial, progress_fn,
						       progress_data, NULL);

	g_main_loop_run (call.loop);

	if (cancellable)
		g_cancellable_disconnect (cancellable, cancel_handler_id);

	success = eas_gdbus_call_finish (client, call.result, call.cancelled ? serial : 0,
					 out_params, &ap, error);

	if (serial && progress_fn) {
		EasProgressCallbackInfo *cbinfo;

		g_mutex_lock (client->progress_lock);
		cbinfo = g_hash_table_lookup (client->progress_fns_table,
					      GUINT_TO_POINTER (serial));
		if (cbinfo && cbinfo->calling) {
			g_debug ("Progress for call %u is running; wait for it to complete",
				 serial);
			g_hash_table_steal (client->progress_fns_table,
					    GUINT_TO_POINTER (serial));
			do {
				g_cond_wait (client->progress_cond, client->progress_lock);
			} while (cbinfo->calling);
			g_free (cbinfo);
		} else if (cbinfo) {
			g_hash_table_remove (client->progress_fns_table,
					     GUINT_TO_POINTER (serial));
		}
		g_mutex_unlock (client->progress_lock);
	}

	va_end (ap);

	g_main_context_pop_thread_default (ctxt);
	g_main_context_unref (ctxt);
	g_main_loop_unref (call.loop);
	g_object_unref (call.result);

	return success;
}