Blame lib/bluetooth-settings-widget.c

Packit Service fc05fa
/*
Packit Service fc05fa
 *
Packit Service fc05fa
 *  Copyright (C) 2013  Bastien Nocera <hadess@hadess.net>
Packit Service fc05fa
 *
Packit Service fc05fa
 *  This library is free software; you can redistribute it and/or
Packit Service fc05fa
 *  modify it under the terms of the GNU Lesser General Public
Packit Service fc05fa
 *  License as published by the Free Software Foundation; either
Packit Service fc05fa
 *  version 2.1 of the License, or (at your option) any later version.
Packit Service fc05fa
 *
Packit Service fc05fa
 *  This library is distributed in the hope that it will be useful,
Packit Service fc05fa
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service fc05fa
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service fc05fa
 *  Lesser General Public License for more details.
Packit Service fc05fa
 *
Packit Service fc05fa
 *  You should have received a copy of the GNU Lesser General Public
Packit Service fc05fa
 *  License along with this library; if not, write to the Free Software
Packit Service fc05fa
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
Packit Service fc05fa
 *
Packit Service fc05fa
 */
Packit Service fc05fa
Packit Service fc05fa
#ifdef HAVE_CONFIG_H
Packit Service fc05fa
#include <config.h>
Packit Service fc05fa
#endif
Packit Service fc05fa
Packit Service fc05fa
#include <gtk/gtk.h>
Packit Service fc05fa
Packit Service fc05fa
#include <glib/gi18n-lib.h>
Packit Service fc05fa
#include <math.h>
Packit Service fc05fa
Packit Service fc05fa
#include "bluetooth-client.h"
Packit Service fc05fa
#include "bluetooth-client-private.h"
Packit Service fc05fa
#include "bluetooth-client-glue.h"
Packit Service fc05fa
#include "bluetooth-agent.h"
Packit Service fc05fa
#include "bluetooth-utils.h"
Packit Service fc05fa
#include "bluetooth-settings-widget.h"
Packit Service fc05fa
#include "bluetooth-settings-resources.h"
Packit Service fc05fa
#include "bluetooth-settings-row.h"
Packit Service fc05fa
#include "bluetooth-settings-obexpush.h"
Packit Service fc05fa
#include "bluetooth-pairing-dialog.h"
Packit Service fc05fa
#include "bluetooth-hdy-column.h"
Packit Service fc05fa
#include "pin.h"
Packit Service fc05fa
Packit Service fc05fa
#define BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE(obj) \
Packit Service fc05fa
	(bluetooth_settings_widget_get_instance_private (obj))
Packit Service fc05fa
Packit Service fc05fa
typedef struct _BluetoothSettingsWidgetPrivate BluetoothSettingsWidgetPrivate;
Packit Service fc05fa
Packit Service fc05fa
struct _BluetoothSettingsWidgetPrivate {
Packit Service fc05fa
	GtkBuilder          *builder;
Packit Service fc05fa
	GtkWidget           *child_box;
Packit Service fc05fa
	BluetoothClient     *client;
Packit Service fc05fa
	GtkTreeModel        *model;
Packit Service fc05fa
	gboolean             debug;
Packit Service fc05fa
	GCancellable        *cancellable;
Packit Service fc05fa
Packit Service fc05fa
	/* Pairing */
Packit Service fc05fa
	BluetoothAgent      *agent;
Packit Service fc05fa
	GtkWidget           *pairing_dialog;
Packit Service fc05fa
	GHashTable          *pairing_devices; /* key=object-path, value=boolean */
Packit Service fc05fa
Packit Service fc05fa
	/* Properties */
Packit Service fc05fa
	GtkWidget           *properties_dialog;
Packit Service fc05fa
	char                *selected_bdaddr;
Packit Service fc05fa
	char                *selected_name;
Packit Service fc05fa
	char                *selected_object_path;
Packit Service fc05fa
Packit Service fc05fa
	/* Device section */
Packit Service fc05fa
	GtkWidget           *device_label;
Packit Service fc05fa
	GtkWidget           *device_list;
Packit Service fc05fa
	GtkAdjustment       *focus_adjustment;
Packit Service fc05fa
	GtkSizeGroup        *row_sizegroup;
Packit Service fc05fa
	GtkWidget           *device_stack;
Packit Service fc05fa
	GtkWidget           *device_spinner;
Packit Service fc05fa
	GHashTable          *connecting_devices; /* key=bdaddr, value=boolean */
Packit Service fc05fa
Packit Service fc05fa
	/* Hack to work-around:
Packit Service fc05fa
	 * http://thread.gmane.org/gmane.linux.bluez.kernel/41471 */
Packit Service fc05fa
	GHashTable          *devices_type; /* key=bdaddr, value=guint32 */
Packit Service fc05fa
Packit Service fc05fa
	/* Sharing section */
Packit Service fc05fa
	GtkWidget           *visible_label;
Packit Service fc05fa
	gboolean             has_console;
Packit Service fc05fa
	GDBusProxy          *session_proxy;
Packit Service fc05fa
};
Packit Service fc05fa
Packit Service fc05fa
G_DEFINE_TYPE_WITH_PRIVATE(BluetoothSettingsWidget, bluetooth_settings_widget, GTK_TYPE_BOX)
Packit Service fc05fa
Packit Service fc05fa
enum {
Packit Service fc05fa
	PANEL_CHANGED,
Packit Service fc05fa
	ADAPTER_STATUS_CHANGED,
Packit Service fc05fa
	LAST_SIGNAL
Packit Service fc05fa
};
Packit Service fc05fa
Packit Service fc05fa
static guint signals[LAST_SIGNAL] = { 0 };
Packit Service fc05fa
Packit Service fc05fa
#define WID(s) GTK_WIDGET (gtk_builder_get_object (priv->builder, s))
Packit Service fc05fa
Packit Service fc05fa
#define KEYBOARD_PREFS		"keyboard"
Packit Service fc05fa
#define MOUSE_PREFS		"mouse"
Packit Service fc05fa
#define SOUND_PREFS		"sound"
Packit Service fc05fa
Packit Service fc05fa
#define ICON_SIZE 128
Packit Service fc05fa
Packit Service fc05fa
/* We'll try to connect to the device repeatedly for that
Packit Service fc05fa
 * amount of time before we bail out */
Packit Service fc05fa
#define CONNECT_TIMEOUT 3.0
Packit Service fc05fa
Packit Service fc05fa
#define BLUEZ_SERVICE	"org.bluez"
Packit Service fc05fa
#define ADAPTER_IFACE	"org.bluez.Adapter1"
Packit Service fc05fa
Packit Service fc05fa
#define AGENT_PATH "/org/gnome/bluetooth/settings"
Packit Service fc05fa
Packit Service fc05fa
#define GNOME_SESSION_DBUS_NAME      "org.gnome.SessionManager"
Packit Service fc05fa
#define GNOME_SESSION_DBUS_OBJECT    "/org/gnome/SessionManager"
Packit Service fc05fa
#define GNOME_SESSION_DBUS_INTERFACE "org.gnome.SessionManager"
Packit Service fc05fa
Packit Service fc05fa
#define FILLER_PAGE                  "filler-page"
Packit Service fc05fa
#define DEVICES_PAGE                 "devices-page"
Packit Service fc05fa
Packit Service fc05fa
enum {
Packit Service fc05fa
	CONNECTING_NOTEBOOK_PAGE_SWITCH = 0,
Packit Service fc05fa
	CONNECTING_NOTEBOOK_PAGE_SPINNER = 1
Packit Service fc05fa
};
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
set_connecting_page (BluetoothSettingsWidget *self,
Packit Service fc05fa
		     int               page)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
Packit Service fc05fa
	if (page == CONNECTING_NOTEBOOK_PAGE_SPINNER)
Packit Service fc05fa
		gtk_spinner_start (GTK_SPINNER (WID ("connecting_spinner")));
Packit Service fc05fa
	gtk_notebook_set_current_page (GTK_NOTEBOOK (WID ("connecting_notebook")), page);
Packit Service fc05fa
	if (page == CONNECTING_NOTEBOOK_PAGE_SWITCH)
Packit Service fc05fa
		gtk_spinner_stop (GTK_SPINNER (WID ("connecting_spinner")));
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
remove_connecting (BluetoothSettingsWidget *self,
Packit Service fc05fa
		   const char       *bdaddr)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	g_hash_table_remove (priv->connecting_devices, bdaddr);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
add_connecting (BluetoothSettingsWidget *self,
Packit Service fc05fa
		const char       *bdaddr)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	g_hash_table_insert (priv->connecting_devices,
Packit Service fc05fa
			     g_strdup (bdaddr),
Packit Service fc05fa
			     GINT_TO_POINTER (1));
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static gboolean
Packit Service fc05fa
is_connecting (BluetoothSettingsWidget *self,
Packit Service fc05fa
	       const char       *bdaddr)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	return GPOINTER_TO_INT (g_hash_table_lookup (priv->connecting_devices,
Packit Service fc05fa
						     bdaddr));
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static gboolean
Packit Service fc05fa
has_default_adapter (BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	g_autofree char *default_adapter = NULL;
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv;
Packit Service fc05fa
Packit Service fc05fa
	priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	g_object_get (priv->client, "default-adapter", &default_adapter, NULL);
Packit Service fc05fa
	return (default_adapter != NULL);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
typedef struct {
Packit Service fc05fa
	char             *bdaddr;
Packit Service fc05fa
	BluetoothSettingsWidget *self;
Packit Service fc05fa
} ConnectData;
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
connect_done (GObject      *source_object,
Packit Service fc05fa
	      GAsyncResult *res,
Packit Service fc05fa
	      gpointer      user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidget *self;
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv;
Packit Service fc05fa
	gboolean success;
Packit Service fc05fa
	GError *error = NULL;
Packit Service fc05fa
	ConnectData *data = (ConnectData *) user_data;
Packit Service fc05fa
Packit Service fc05fa
	success = bluetooth_client_connect_service_finish (BLUETOOTH_CLIENT (source_object),
Packit Service fc05fa
							   res, &error);
Packit Service fc05fa
	if (!success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
Packit Service fc05fa
		goto out;
Packit Service fc05fa
Packit Service fc05fa
	self = data->self;
Packit Service fc05fa
	priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
Packit Service fc05fa
	/* Check whether the same device is now selected, and update the UI */
Packit Service fc05fa
	if (g_strcmp0 (priv->selected_bdaddr, data->bdaddr) == 0) {
Packit Service fc05fa
		GtkSwitch *button;
Packit Service fc05fa
Packit Service fc05fa
		button = GTK_SWITCH (WID ("switch_connection"));
Packit Service fc05fa
Packit Service fc05fa
		/* Ensure the switch position is in the correct place. */
Packit Service fc05fa
		gtk_switch_set_active (button, gtk_switch_get_state (button));
Packit Service fc05fa
Packit Service fc05fa
		if (success == FALSE) {
Packit Service fc05fa
			g_debug ("Connection failed to %s: %s", data->bdaddr, error->message);
Packit Service fc05fa
		}
Packit Service fc05fa
		set_connecting_page (self, CONNECTING_NOTEBOOK_PAGE_SWITCH);
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	g_clear_error (&error);
Packit Service fc05fa
	remove_connecting (self, data->bdaddr);
Packit Service fc05fa
Packit Service fc05fa
	//FIXME show an error if it failed?
Packit Service fc05fa
	g_object_set (G_OBJECT (priv->client),
Packit Service fc05fa
		      "default-adapter-discovering", has_default_adapter (self),
Packit Service fc05fa
		      NULL);
Packit Service fc05fa
Packit Service fc05fa
out:
Packit Service fc05fa
	g_clear_error (&error);
Packit Service fc05fa
	g_free (data->bdaddr);
Packit Service fc05fa
	g_free (data);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
add_device_type (BluetoothSettingsWidget *self,
Packit Service fc05fa
		 const char              *bdaddr,
Packit Service fc05fa
		 BluetoothType            type)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	BluetoothType t;
Packit Service fc05fa
Packit Service fc05fa
	t = GPOINTER_TO_UINT (g_hash_table_lookup (priv->devices_type, bdaddr));
Packit Service fc05fa
	if (t == 0 || t == BLUETOOTH_TYPE_ANY) {
Packit Service fc05fa
		g_hash_table_insert (priv->devices_type, g_strdup (bdaddr), GUINT_TO_POINTER (type));
Packit Service fc05fa
		g_debug ("Saving device type %s for %s", bluetooth_type_to_string (type), bdaddr);
Packit Service fc05fa
	}
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
setup_pairing_dialog (BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	GtkWidget *toplevel;
Packit Service fc05fa
Packit Service fc05fa
	g_clear_pointer (&priv->pairing_dialog, gtk_widget_destroy);
Packit Service fc05fa
	priv->pairing_dialog = bluetooth_pairing_dialog_new ();
Packit Service fc05fa
	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
Packit Service fc05fa
	gtk_window_set_transient_for (GTK_WINDOW (priv->pairing_dialog), GTK_WINDOW (toplevel));
Packit Service fc05fa
	gtk_window_set_modal (GTK_WINDOW (priv->pairing_dialog), TRUE);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static gboolean
Packit Service fc05fa
get_properties_for_device (BluetoothSettingsWidget  *self,
Packit Service fc05fa
			   GDBusProxy               *device,
Packit Service fc05fa
			   char                    **name,
Packit Service fc05fa
			   char                    **ret_bdaddr,
Packit Service fc05fa
			   BluetoothType            *type)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	GVariant *value;
Packit Service fc05fa
	char *bdaddr;
Packit Service fc05fa
Packit Service fc05fa
	g_return_val_if_fail (name != NULL, FALSE);
Packit Service fc05fa
Packit Service fc05fa
	value = g_dbus_proxy_get_cached_property (device, "Name");
Packit Service fc05fa
	if (value == NULL) {
Packit Service fc05fa
		/* What?! */
Packit Service fc05fa
		return FALSE;
Packit Service fc05fa
	}
Packit Service fc05fa
	*name = g_variant_dup_string (value, NULL);
Packit Service fc05fa
	g_variant_unref (value);
Packit Service fc05fa
Packit Service fc05fa
	value = g_dbus_proxy_get_cached_property (device, "Address");
Packit Service fc05fa
	bdaddr = g_variant_dup_string (value, NULL);
Packit Service fc05fa
	g_variant_unref (value);
Packit Service fc05fa
Packit Service fc05fa
	if (ret_bdaddr)
Packit Service fc05fa
		*ret_bdaddr = g_strdup (bdaddr);
Packit Service fc05fa
Packit Service fc05fa
	if (type) {
Packit Service fc05fa
		value = g_dbus_proxy_get_cached_property (device, "Class");
Packit Service fc05fa
		if (value != NULL) {
Packit Service fc05fa
			*type = bluetooth_class_to_type (g_variant_get_uint32 (value));
Packit Service fc05fa
			g_variant_unref (value);
Packit Service fc05fa
		} else {
Packit Service fc05fa
			*type = GPOINTER_TO_UINT (g_hash_table_lookup (priv->devices_type, bdaddr));
Packit Service fc05fa
			if (*type == 0)
Packit Service fc05fa
				*type = BLUETOOTH_TYPE_ANY;
Packit Service fc05fa
		}
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	g_free (bdaddr);
Packit Service fc05fa
Packit Service fc05fa
	return TRUE;
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static char *
Packit Service fc05fa
get_random_pincode (guint num_digits)
Packit Service fc05fa
{
Packit Service fc05fa
	if (num_digits == 0)
Packit Service fc05fa
		num_digits = PIN_NUM_DIGITS;
Packit Service fc05fa
	return g_strdup_printf ("%d", g_random_int_range (pow (10, num_digits - 1),
Packit Service fc05fa
							  pow (10, num_digits)));
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static char *
Packit Service fc05fa
get_icade_pincode (char **pin_display_str)
Packit Service fc05fa
{
Packit Service fc05fa
	GString *pin, *pin_display;
Packit Service fc05fa
	guint i;
Packit Service fc05fa
	static char *arrows[] = {
Packit Service fc05fa
		NULL,
Packit Service fc05fa
		"⬆", /* up = 1    */
Packit Service fc05fa
		"⬇", /* down = 2  */
Packit Service fc05fa
		"⬅", /* left = 3  */
Packit Service fc05fa
		"➡"  /* right = 4 */
Packit Service fc05fa
	};
Packit Service fc05fa
Packit Service fc05fa
	pin = g_string_new (NULL);
Packit Service fc05fa
	pin_display = g_string_new (NULL);
Packit Service fc05fa
Packit Service fc05fa
	for (i = 0; i < PIN_NUM_DIGITS; i++) {
Packit Service fc05fa
		int r;
Packit Service fc05fa
		char *c;
Packit Service fc05fa
Packit Service fc05fa
		r = g_random_int_range (1, 5);
Packit Service fc05fa
Packit Service fc05fa
		c = g_strdup_printf ("%d", r);
Packit Service fc05fa
		g_string_append (pin, c);
Packit Service fc05fa
		g_free (c);
Packit Service fc05fa
Packit Service fc05fa
		g_string_append (pin_display, arrows[r]);
Packit Service fc05fa
	}
Packit Service fc05fa
	g_string_append (pin_display, "❍");
Packit Service fc05fa
Packit Service fc05fa
	*pin_display_str = g_string_free (pin_display, FALSE);
Packit Service fc05fa
	return g_string_free (pin, FALSE);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
display_cb (GtkDialog *dialog,
Packit Service fc05fa
	    int        response,
Packit Service fc05fa
	    gpointer   user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (user_data);
Packit Service fc05fa
Packit Service fc05fa
	g_clear_pointer (&priv->pairing_dialog, gtk_widget_destroy);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
enter_pin_cb (GtkDialog *dialog,
Packit Service fc05fa
	      int        response,
Packit Service fc05fa
	      gpointer   user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (user_data);
Packit Service fc05fa
	GDBusMethodInvocation *invocation;
Packit Service fc05fa
Packit Service fc05fa
	invocation = g_object_get_data (G_OBJECT (dialog), "invocation");
Packit Service fc05fa
Packit Service fc05fa
	if (response == GTK_RESPONSE_ACCEPT) {
Packit Service fc05fa
		const char *name;
Packit Service fc05fa
		char *pin;
Packit Service fc05fa
		BluetoothPairingMode mode;
Packit Service fc05fa
Packit Service fc05fa
		mode = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (dialog), "mode"));
Packit Service fc05fa
		name = g_object_get_data (G_OBJECT (dialog), "name");
Packit Service fc05fa
		pin = bluetooth_pairing_dialog_get_pin (BLUETOOTH_PAIRING_DIALOG (dialog));
Packit Service fc05fa
		g_dbus_method_invocation_return_value (invocation,
Packit Service fc05fa
						       g_variant_new ("(s)", pin));
Packit Service fc05fa
Packit Service fc05fa
		if (bluetooth_pairing_dialog_get_mode (BLUETOOTH_PAIRING_DIALOG (priv->pairing_dialog)) == BLUETOOTH_PAIRING_MODE_PIN_QUERY) {
Packit Service fc05fa
			g_clear_pointer (&priv->pairing_dialog, gtk_widget_destroy);
Packit Service fc05fa
			return;
Packit Service fc05fa
		}
Packit Service fc05fa
		bluetooth_pairing_dialog_set_mode (BLUETOOTH_PAIRING_DIALOG (priv->pairing_dialog),
Packit Service fc05fa
						   mode, pin, name);
Packit Service fc05fa
		g_free (pin);
Packit Service fc05fa
		g_signal_connect (G_OBJECT (priv->pairing_dialog), "response",
Packit Service fc05fa
				  G_CALLBACK (display_cb), user_data);
Packit Service fc05fa
	} else {
Packit Service fc05fa
		g_dbus_method_invocation_return_dbus_error (invocation,
Packit Service fc05fa
							    "org.bluez.Error.Canceled",
Packit Service fc05fa
							    "User cancelled pairing");
Packit Service fc05fa
		g_clear_pointer (&priv->pairing_dialog, gtk_widget_destroy);
Packit Service fc05fa
		return;
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	g_object_set_data (G_OBJECT (priv->pairing_dialog), "invocation", NULL);
Packit Service fc05fa
	g_object_set_data (G_OBJECT (priv->pairing_dialog), "mode", NULL);
Packit Service fc05fa
	g_object_set_data (G_OBJECT (priv->pairing_dialog), "name", NULL);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
confirm_remote_pin_cb (GtkDialog *dialog,
Packit Service fc05fa
		       int        response,
Packit Service fc05fa
		       gpointer   user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (user_data);
Packit Service fc05fa
	GDBusMethodInvocation *invocation;
Packit Service fc05fa
Packit Service fc05fa
	invocation = g_object_get_data (G_OBJECT (dialog), "invocation");
Packit Service fc05fa
Packit Service fc05fa
	if (response == GTK_RESPONSE_ACCEPT) {
Packit Service fc05fa
		GDBusProxy *device;
Packit Service fc05fa
		const char *pin;
Packit Service fc05fa
Packit Service fc05fa
		pin = g_object_get_data (G_OBJECT (invocation), "pin");
Packit Service fc05fa
		device = g_object_get_data (G_OBJECT (invocation), "device");
Packit Service fc05fa
Packit Service fc05fa
		bluetooth_client_set_trusted (priv->client, g_dbus_proxy_get_object_path (device), TRUE);
Packit Service fc05fa
Packit Service fc05fa
		g_dbus_method_invocation_return_value (invocation,
Packit Service fc05fa
						       g_variant_new ("(s)", pin));
Packit Service fc05fa
	} else {
Packit Service fc05fa
		g_dbus_method_invocation_return_dbus_error (invocation, "org.bluez.Error.Rejected", "Pairing refused from settings panel");
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	g_clear_pointer (&priv->pairing_dialog, gtk_widget_destroy);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
pincode_callback (GDBusMethodInvocation *invocation,
Packit Service fc05fa
		  GDBusProxy            *device,
Packit Service fc05fa
		  gpointer               user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidget *self = user_data;
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (user_data);
Packit Service fc05fa
	BluetoothType type;
Packit Service fc05fa
	char *name, *bdaddr;
Packit Service fc05fa
	guint max_digits;
Packit Service fc05fa
	gboolean confirm_pin = TRUE;
Packit Service fc05fa
	char *default_pin;
Packit Service fc05fa
	char *display_pin = NULL;
Packit Service fc05fa
	BluetoothPairingMode mode;
Packit Service fc05fa
	gboolean remote_initiated;
Packit Service fc05fa
Packit Service fc05fa
	g_debug ("pincode_callback (%s)", g_dbus_proxy_get_object_path (device));
Packit Service fc05fa
Packit Service fc05fa
	if (!get_properties_for_device (self, device, &name, &bdaddr, &type)) {
Packit Service fc05fa
		char *msg;
Packit Service fc05fa
Packit Service fc05fa
		msg = g_strdup_printf ("Missing information for %s", g_dbus_proxy_get_object_path (device));
Packit Service fc05fa
		g_dbus_method_invocation_return_dbus_error (invocation, "org.bluez.Error.Rejected", msg);
Packit Service fc05fa
		g_free (msg);
Packit Service fc05fa
		return;
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	remote_initiated = !GPOINTER_TO_UINT (g_hash_table_lookup (priv->pairing_devices,
Packit Service fc05fa
								   g_dbus_proxy_get_object_path (device)));
Packit Service fc05fa
Packit Service fc05fa
	default_pin = get_pincode_for_device (type, bdaddr, name, &max_digits, &confirm_pin);
Packit Service fc05fa
	if (g_strcmp0 (default_pin, "KEYBOARD") == 0) {
Packit Service fc05fa
		mode = BLUETOOTH_PAIRING_MODE_PIN_DISPLAY_KEYBOARD;
Packit Service fc05fa
		g_free (default_pin);
Packit Service fc05fa
		default_pin = get_random_pincode (max_digits);
Packit Service fc05fa
		display_pin = g_strdup_printf ("%s⏎", default_pin);
Packit Service fc05fa
	} else if (g_strcmp0 (default_pin, "ICADE") == 0) {
Packit Service fc05fa
		mode = BLUETOOTH_PAIRING_MODE_PIN_DISPLAY_ICADE;
Packit Service fc05fa
		confirm_pin = FALSE;
Packit Service fc05fa
		g_free (default_pin);
Packit Service fc05fa
		default_pin = get_icade_pincode (&display_pin);
Packit Service fc05fa
	} else if (default_pin == NULL) {
Packit Service fc05fa
		mode = BLUETOOTH_PAIRING_MODE_PIN_DISPLAY_NORMAL;
Packit Service fc05fa
		confirm_pin = TRUE;
Packit Service fc05fa
		default_pin = get_random_pincode (0);
Packit Service fc05fa
	} else if (g_strcmp0 (default_pin, "NULL") == 0) {
Packit Service fc05fa
		g_assert_not_reached ();
Packit Service fc05fa
	} else {
Packit Service fc05fa
		mode = BLUETOOTH_PAIRING_MODE_PIN_DISPLAY_NORMAL;
Packit Service fc05fa
		display_pin = g_strdup (default_pin);
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	setup_pairing_dialog (BLUETOOTH_SETTINGS_WIDGET (user_data));
Packit Service fc05fa
Packit Service fc05fa
	g_object_set_data_full (G_OBJECT (priv->pairing_dialog), "name", g_strdup (name), g_free);
Packit Service fc05fa
	g_object_set_data (G_OBJECT (priv->pairing_dialog), "mode", GUINT_TO_POINTER (mode));
Packit Service fc05fa
Packit Service fc05fa
	if (confirm_pin) {
Packit Service fc05fa
		g_object_set_data (G_OBJECT (priv->pairing_dialog), "invocation", invocation);
Packit Service fc05fa
		if (remote_initiated) {
Packit Service fc05fa
			bluetooth_pairing_dialog_set_mode (BLUETOOTH_PAIRING_DIALOG (priv->pairing_dialog),
Packit Service fc05fa
							   BLUETOOTH_PAIRING_MODE_PIN_QUERY,
Packit Service fc05fa
							   default_pin,
Packit Service fc05fa
							   name);
Packit Service fc05fa
		} else {
Packit Service fc05fa
			bluetooth_pairing_dialog_set_mode (BLUETOOTH_PAIRING_DIALOG (priv->pairing_dialog),
Packit Service fc05fa
							   BLUETOOTH_PAIRING_MODE_PIN_CONFIRMATION,
Packit Service fc05fa
							   default_pin,
Packit Service fc05fa
							   name);
Packit Service fc05fa
		}
Packit Service fc05fa
		g_signal_connect (G_OBJECT (priv->pairing_dialog), "response",
Packit Service fc05fa
				  G_CALLBACK (enter_pin_cb), user_data);
Packit Service fc05fa
	} else if (!remote_initiated) {
Packit Service fc05fa
		bluetooth_pairing_dialog_set_mode (BLUETOOTH_PAIRING_DIALOG (priv->pairing_dialog),
Packit Service fc05fa
						   mode, display_pin, name);
Packit Service fc05fa
		g_dbus_method_invocation_return_value (invocation,
Packit Service fc05fa
						       g_variant_new ("(s)", default_pin));
Packit Service fc05fa
		g_signal_connect (G_OBJECT (priv->pairing_dialog), "response",
Packit Service fc05fa
				  G_CALLBACK (display_cb), user_data);
Packit Service fc05fa
	} else {
Packit Service fc05fa
		bluetooth_pairing_dialog_set_mode (BLUETOOTH_PAIRING_DIALOG (priv->pairing_dialog),
Packit Service fc05fa
						   BLUETOOTH_PAIRING_MODE_YES_NO,
Packit Service fc05fa
						   default_pin, name);
Packit Service fc05fa
Packit Service fc05fa
		g_object_set_data_full (G_OBJECT (invocation), "pin", g_strdup (default_pin), g_free);
Packit Service fc05fa
		g_object_set_data_full (G_OBJECT (invocation), "device", g_object_ref (device), g_object_unref);
Packit Service fc05fa
		g_object_set_data (G_OBJECT (priv->pairing_dialog), "invocation", invocation);
Packit Service fc05fa
Packit Service fc05fa
		g_signal_connect (G_OBJECT (priv->pairing_dialog), "response",
Packit Service fc05fa
				  G_CALLBACK (confirm_remote_pin_cb), user_data);
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	g_free (name);
Packit Service fc05fa
	g_free (bdaddr);
Packit Service fc05fa
	g_free (default_pin);
Packit Service fc05fa
	g_free (display_pin);
Packit Service fc05fa
Packit Service fc05fa
	gtk_widget_show (priv->pairing_dialog);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
display_callback (GDBusMethodInvocation *invocation,
Packit Service fc05fa
		  GDBusProxy            *device,
Packit Service fc05fa
		  guint                  pin,
Packit Service fc05fa
		  guint                  entered,
Packit Service fc05fa
		  gpointer               user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidget *self = user_data;
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (user_data);
Packit Service fc05fa
	char *pin_str, *name;
Packit Service fc05fa
Packit Service fc05fa
	g_debug ("display_callback (%s, %i, %i)", g_dbus_proxy_get_object_path (device), pin, entered);
Packit Service fc05fa
Packit Service fc05fa
	if (priv->pairing_dialog == NULL ||
Packit Service fc05fa
	    bluetooth_pairing_dialog_get_mode (BLUETOOTH_PAIRING_DIALOG (priv->pairing_dialog)) != BLUETOOTH_PAIRING_MODE_PIN_DISPLAY_KEYBOARD)
Packit Service fc05fa
		setup_pairing_dialog (BLUETOOTH_SETTINGS_WIDGET (user_data));
Packit Service fc05fa
Packit Service fc05fa
	pin_str = g_strdup_printf ("%06d", pin);
Packit Service fc05fa
	get_properties_for_device (self, device, &name, NULL, NULL);
Packit Service fc05fa
	bluetooth_pairing_dialog_set_mode (BLUETOOTH_PAIRING_DIALOG (priv->pairing_dialog),
Packit Service fc05fa
					   BLUETOOTH_PAIRING_MODE_PIN_DISPLAY_KEYBOARD,
Packit Service fc05fa
					   pin_str,
Packit Service fc05fa
					   name);
Packit Service fc05fa
	bluetooth_pairing_dialog_set_pin_entered (BLUETOOTH_PAIRING_DIALOG (priv->pairing_dialog),
Packit Service fc05fa
						  entered);
Packit Service fc05fa
	g_free (pin_str);
Packit Service fc05fa
	g_free (name);
Packit Service fc05fa
Packit Service fc05fa
	gtk_widget_show (priv->pairing_dialog);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
display_pincode_callback (GDBusMethodInvocation *invocation,
Packit Service fc05fa
			  GDBusProxy            *device,
Packit Service fc05fa
			  const char            *pincode,
Packit Service fc05fa
			  gpointer               user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidget *self = user_data;
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (user_data);
Packit Service fc05fa
	BluetoothType type;
Packit Service fc05fa
	char *display_pin = NULL;
Packit Service fc05fa
	char *name, *bdaddr;
Packit Service fc05fa
	char *db_pin;
Packit Service fc05fa
Packit Service fc05fa
	g_debug ("display_pincode_callback (%s, %s)", g_dbus_proxy_get_object_path (device), pincode);
Packit Service fc05fa
Packit Service fc05fa
	if (!get_properties_for_device (self, device, &name, &bdaddr, &type)) {
Packit Service fc05fa
		char *msg;
Packit Service fc05fa
Packit Service fc05fa
		msg = g_strdup_printf ("Missing information for %s", g_dbus_proxy_get_object_path (device));
Packit Service fc05fa
		g_dbus_method_invocation_return_dbus_error (invocation, "org.bluez.Error.Rejected", msg);
Packit Service fc05fa
		g_free (msg);
Packit Service fc05fa
		return;
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	/* Verify PIN code validity */
Packit Service fc05fa
	db_pin = get_pincode_for_device (type,
Packit Service fc05fa
					 bdaddr,
Packit Service fc05fa
					 name,
Packit Service fc05fa
					 NULL,
Packit Service fc05fa
					 NULL);
Packit Service fc05fa
	if (g_strcmp0 (db_pin, "KEYBOARD") == 0) {
Packit Service fc05fa
		/* Should work, follow through */
Packit Service fc05fa
	} else if (g_strcmp0 (db_pin, "ICADE") == 0) {
Packit Service fc05fa
		char *msg;
Packit Service fc05fa
Packit Service fc05fa
		msg = g_strdup_printf ("Generated pincode for %s when it shouldn't have", name);
Packit Service fc05fa
		g_dbus_method_invocation_return_dbus_error (invocation, "org.bluez.Error.Rejected", msg);
Packit Service fc05fa
		g_free (msg);
Packit Service fc05fa
		goto bail;
Packit Service fc05fa
	} else if (g_strcmp0 (db_pin, "0000") == 0) {
Packit Service fc05fa
		g_debug ("Ignoring generated keyboard PIN '%s', should get 0000 soon", pincode);
Packit Service fc05fa
		g_dbus_method_invocation_return_value (invocation, NULL);
Packit Service fc05fa
		goto bail;
Packit Service fc05fa
	} else if (g_strcmp0 (db_pin, "NULL") == 0) {
Packit Service fc05fa
		char *msg;
Packit Service fc05fa
Packit Service fc05fa
		msg = g_strdup_printf ("Attempting pairing for %s that doesn't support pairing", name);
Packit Service fc05fa
		g_dbus_method_invocation_return_dbus_error (invocation, "org.bluez.Error.Rejected", msg);
Packit Service fc05fa
		g_free (msg);
Packit Service fc05fa
		goto bail;
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	setup_pairing_dialog (BLUETOOTH_SETTINGS_WIDGET (user_data));
Packit Service fc05fa
Packit Service fc05fa
	display_pin = g_strdup_printf ("%s⏎", pincode);
Packit Service fc05fa
	bluetooth_pairing_dialog_set_mode (BLUETOOTH_PAIRING_DIALOG (priv->pairing_dialog),
Packit Service fc05fa
					   BLUETOOTH_PAIRING_MODE_PIN_DISPLAY_KEYBOARD,
Packit Service fc05fa
					   display_pin,
Packit Service fc05fa
					   name);
Packit Service fc05fa
	gtk_widget_show (priv->pairing_dialog);
Packit Service fc05fa
Packit Service fc05fa
	g_dbus_method_invocation_return_value (invocation, NULL);
Packit Service fc05fa
Packit Service fc05fa
bail:
Packit Service fc05fa
	g_free (db_pin);
Packit Service fc05fa
	g_free (display_pin);
Packit Service fc05fa
	g_free (bdaddr);
Packit Service fc05fa
	g_free (name);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
passkey_callback (GDBusMethodInvocation *invocation,
Packit Service fc05fa
		  GDBusProxy            *device,
Packit Service fc05fa
		  gpointer               data)
Packit Service fc05fa
{
Packit Service fc05fa
	g_warning ("RequestPasskey(): not implemented");
Packit Service fc05fa
	g_dbus_method_invocation_return_dbus_error (invocation,
Packit Service fc05fa
						    "org.bluez.Error.Rejected",
Packit Service fc05fa
						    "RequestPasskey not implemented");
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static gboolean
Packit Service fc05fa
cancel_callback (GDBusMethodInvocation *invocation,
Packit Service fc05fa
		 gpointer               user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (user_data);
Packit Service fc05fa
	GList *l, *children;
Packit Service fc05fa
Packit Service fc05fa
	g_debug ("cancel_callback ()");
Packit Service fc05fa
Packit Service fc05fa
	g_clear_pointer (&priv->pairing_dialog, gtk_widget_destroy);
Packit Service fc05fa
Packit Service fc05fa
	children = gtk_container_get_children (GTK_CONTAINER (priv->device_list));
Packit Service fc05fa
	for (l = children; l != NULL; l = l->next)
Packit Service fc05fa
		g_object_set (l->data, "pairing", FALSE, NULL);
Packit Service fc05fa
	g_list_free (children);
Packit Service fc05fa
Packit Service fc05fa
	g_dbus_method_invocation_return_value (invocation, NULL);
Packit Service fc05fa
Packit Service fc05fa
	return TRUE;
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
confirm_cb (GtkDialog *dialog,
Packit Service fc05fa
	    int        response,
Packit Service fc05fa
	    gpointer   user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (user_data);
Packit Service fc05fa
	GDBusMethodInvocation *invocation;
Packit Service fc05fa
Packit Service fc05fa
	invocation = g_object_get_data (G_OBJECT (dialog), "invocation");
Packit Service fc05fa
	if (response == GTK_RESPONSE_ACCEPT) {
Packit Service fc05fa
		g_dbus_method_invocation_return_value (invocation, NULL);
Packit Service fc05fa
	} else {
Packit Service fc05fa
		g_dbus_method_invocation_return_dbus_error (invocation,
Packit Service fc05fa
							    "org.bluez.Error.Canceled",
Packit Service fc05fa
							    "User cancelled pairing");
Packit Service fc05fa
	}
Packit Service fc05fa
	g_clear_pointer (&priv->pairing_dialog, gtk_widget_destroy);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
confirm_callback (GDBusMethodInvocation *invocation,
Packit Service fc05fa
		  GDBusProxy            *device,
Packit Service fc05fa
		  guint                  pin,
Packit Service fc05fa
		  gpointer               user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidget *self = user_data;
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (user_data);
Packit Service fc05fa
	char *name, *pin_str;
Packit Service fc05fa
Packit Service fc05fa
	g_debug ("confirm_callback (%s, %i)", g_dbus_proxy_get_object_path (device), pin);
Packit Service fc05fa
Packit Service fc05fa
	setup_pairing_dialog (BLUETOOTH_SETTINGS_WIDGET (user_data));
Packit Service fc05fa
Packit Service fc05fa
	pin_str = g_strdup_printf ("%06d", pin);
Packit Service fc05fa
	get_properties_for_device (self, device, &name, NULL, NULL);
Packit Service fc05fa
	bluetooth_pairing_dialog_set_mode (BLUETOOTH_PAIRING_DIALOG (priv->pairing_dialog),
Packit Service fc05fa
					   BLUETOOTH_PAIRING_MODE_PIN_MATCH,
Packit Service fc05fa
					   pin_str, name);
Packit Service fc05fa
Packit Service fc05fa
	g_signal_connect (G_OBJECT (priv->pairing_dialog), "response",
Packit Service fc05fa
			  G_CALLBACK (confirm_cb), user_data);
Packit Service fc05fa
	g_object_set_data (G_OBJECT (priv->pairing_dialog), "invocation", invocation);
Packit Service fc05fa
Packit Service fc05fa
	gtk_widget_show (priv->pairing_dialog);
Packit Service fc05fa
Packit Service fc05fa
	g_free (pin_str);
Packit Service fc05fa
	g_free (name);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
authorize_callback (GDBusMethodInvocation *invocation,
Packit Service fc05fa
		    GDBusProxy            *device,
Packit Service fc05fa
		    gpointer               user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidget *self = user_data;
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (user_data);
Packit Service fc05fa
	char *name;
Packit Service fc05fa
Packit Service fc05fa
	g_debug ("authorize_callback (%s)", g_dbus_proxy_get_object_path (device));
Packit Service fc05fa
Packit Service fc05fa
	setup_pairing_dialog (BLUETOOTH_SETTINGS_WIDGET (user_data));
Packit Service fc05fa
	get_properties_for_device (self, device, &name, NULL, NULL);
Packit Service fc05fa
	bluetooth_pairing_dialog_set_mode (BLUETOOTH_PAIRING_DIALOG (priv->pairing_dialog),
Packit Service fc05fa
					   BLUETOOTH_PAIRING_MODE_YES_NO,
Packit Service fc05fa
					   NULL, name);
Packit Service fc05fa
Packit Service fc05fa
	g_signal_connect (G_OBJECT (priv->pairing_dialog), "response",
Packit Service fc05fa
			  G_CALLBACK (confirm_cb), user_data);
Packit Service fc05fa
	g_object_set_data (G_OBJECT (priv->pairing_dialog), "invocation", invocation);
Packit Service fc05fa
Packit Service fc05fa
	gtk_widget_show (priv->pairing_dialog);
Packit Service fc05fa
Packit Service fc05fa
	g_free (name);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
authorize_service_cb (GtkDialog *dialog,
Packit Service fc05fa
		      int        response,
Packit Service fc05fa
		      gpointer   user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (user_data);
Packit Service fc05fa
	GDBusMethodInvocation *invocation;
Packit Service fc05fa
Packit Service fc05fa
	invocation = g_object_get_data (G_OBJECT (dialog), "invocation");
Packit Service fc05fa
Packit Service fc05fa
	if (response == GTK_RESPONSE_ACCEPT) {
Packit Service fc05fa
		GDBusProxy *device;
Packit Service fc05fa
Packit Service fc05fa
		device = g_object_get_data (G_OBJECT (invocation), "device");
Packit Service fc05fa
		bluetooth_client_set_trusted (priv->client, g_dbus_proxy_get_object_path (device), TRUE);
Packit Service fc05fa
		g_dbus_method_invocation_return_value (invocation, NULL);
Packit Service fc05fa
	} else {
Packit Service fc05fa
		char *msg;
Packit Service fc05fa
Packit Service fc05fa
		msg = g_strdup_printf ("Rejecting service auth (HID): not paired or trusted");
Packit Service fc05fa
		g_dbus_method_invocation_return_dbus_error (invocation, "org.bluez.Error.Rejected", msg);
Packit Service fc05fa
		g_free (msg);
Packit Service fc05fa
	}
Packit Service fc05fa
	g_clear_pointer (&priv->pairing_dialog, gtk_widget_destroy);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
authorize_service_callback (GDBusMethodInvocation *invocation,
Packit Service fc05fa
			    GDBusProxy            *device,
Packit Service fc05fa
			    const char            *uuid,
Packit Service fc05fa
			    gpointer               user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidget *self = user_data;
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (user_data);
Packit Service fc05fa
	char *msg;
Packit Service fc05fa
	GVariant *value;
Packit Service fc05fa
	gboolean paired, trusted;
Packit Service fc05fa
Packit Service fc05fa
	g_debug ("authorize_service_callback (%s, %s)", g_dbus_proxy_get_object_path (device), uuid);
Packit Service fc05fa
Packit Service fc05fa
	value = g_dbus_proxy_get_cached_property (device, "Paired");
Packit Service fc05fa
	paired = g_variant_get_boolean (value);
Packit Service fc05fa
	g_variant_unref (value);
Packit Service fc05fa
Packit Service fc05fa
	value = g_dbus_proxy_get_cached_property (device, "Trusted");
Packit Service fc05fa
	trusted = g_variant_get_boolean (value);
Packit Service fc05fa
	g_variant_unref (value);
Packit Service fc05fa
Packit Service fc05fa
	/* Device was paired, initiated from the remote device,
Packit Service fc05fa
	 * so we didn't get the opportunity to set the trusted bit */
Packit Service fc05fa
	if (paired && !trusted) {
Packit Service fc05fa
		bluetooth_client_set_trusted (priv->client,
Packit Service fc05fa
					      g_dbus_proxy_get_object_path (device), TRUE);
Packit Service fc05fa
		g_dbus_method_invocation_return_value (invocation, NULL);
Packit Service fc05fa
		return;
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	if (g_strcmp0 (bluetooth_uuid_to_string (uuid), "HumanInterfaceDeviceService") != 0) {
Packit Service fc05fa
		msg = g_strdup_printf ("Rejecting service auth (%s) for %s: not HID",
Packit Service fc05fa
				       uuid, g_dbus_proxy_get_object_path (device));
Packit Service fc05fa
		g_dbus_method_invocation_return_dbus_error (invocation, "org.bluez.Error.Rejected", msg);
Packit Service fc05fa
		g_free (msg);
Packit Service fc05fa
		return;
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	/* We shouldn't get asked, but shizzle happens */
Packit Service fc05fa
	if (paired || trusted) {
Packit Service fc05fa
		g_dbus_method_invocation_return_value (invocation, NULL);
Packit Service fc05fa
	} else {
Packit Service fc05fa
		char *name;
Packit Service fc05fa
Packit Service fc05fa
		setup_pairing_dialog (BLUETOOTH_SETTINGS_WIDGET (user_data));
Packit Service fc05fa
		get_properties_for_device (self, device, &name, NULL, NULL);
Packit Service fc05fa
		bluetooth_pairing_dialog_set_mode (BLUETOOTH_PAIRING_DIALOG (priv->pairing_dialog),
Packit Service fc05fa
						   BLUETOOTH_PAIRING_MODE_CONFIRM_AUTH,
Packit Service fc05fa
						   NULL, name);
Packit Service fc05fa
Packit Service fc05fa
		g_signal_connect (G_OBJECT (priv->pairing_dialog), "response",
Packit Service fc05fa
				  G_CALLBACK (authorize_service_cb), user_data);
Packit Service fc05fa
		g_object_set_data_full (G_OBJECT (invocation), "device", g_object_ref (device), g_object_unref);
Packit Service fc05fa
		g_object_set_data (G_OBJECT (priv->pairing_dialog), "invocation", invocation);
Packit Service fc05fa
Packit Service fc05fa
		gtk_widget_show (priv->pairing_dialog);
Packit Service fc05fa
Packit Service fc05fa
		g_free (name);
Packit Service fc05fa
	}
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
turn_off_pairing (BluetoothSettingsWidget *self,
Packit Service fc05fa
		  const char              *object_path)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	GList *l, *children;
Packit Service fc05fa
Packit Service fc05fa
	children = gtk_container_get_children (GTK_CONTAINER (priv->device_list));
Packit Service fc05fa
	for (l = children; l != NULL; l = l->next) {
Packit Service fc05fa
		GDBusProxy *proxy;
Packit Service fc05fa
Packit Service fc05fa
		g_object_get (l->data, "proxy", &proxy, NULL);
Packit Service fc05fa
		if (g_strcmp0 (g_dbus_proxy_get_object_path (proxy), object_path) == 0) {
Packit Service fc05fa
			g_object_set (l->data, "pairing", FALSE, NULL);
Packit Service fc05fa
			g_object_unref (proxy);
Packit Service fc05fa
			break;
Packit Service fc05fa
		}
Packit Service fc05fa
		g_object_unref (proxy);
Packit Service fc05fa
	}
Packit Service fc05fa
	g_list_free (children);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
typedef struct {
Packit Service fc05fa
	BluetoothSettingsWidget *self;
Packit Service fc05fa
	char *device;
Packit Service fc05fa
	GTimer *timer;
Packit Service fc05fa
	guint timeout_id;
Packit Service fc05fa
} SetupConnectData;
Packit Service fc05fa
Packit Service fc05fa
static void connect_callback (GObject      *source_object,
Packit Service fc05fa
			      GAsyncResult *res,
Packit Service fc05fa
			      gpointer      user_data);
Packit Service fc05fa
Packit Service fc05fa
static gboolean
Packit Service fc05fa
connect_timeout_cb (gpointer user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	SetupConnectData *data = (SetupConnectData *) user_data;
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (data->self);
Packit Service fc05fa
Packit Service fc05fa
	bluetooth_client_connect_service (priv->client, data->device, TRUE, NULL, connect_callback, data);
Packit Service fc05fa
	data->timeout_id = 0;
Packit Service fc05fa
Packit Service fc05fa
	return G_SOURCE_REMOVE;
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
connect_callback (GObject      *source_object,
Packit Service fc05fa
		  GAsyncResult *res,
Packit Service fc05fa
		  gpointer      user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	SetupConnectData *data = (SetupConnectData *) user_data;
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv;
Packit Service fc05fa
	GError *error = NULL;
Packit Service fc05fa
	gboolean success;
Packit Service fc05fa
Packit Service fc05fa
	success = bluetooth_client_connect_service_finish (BLUETOOTH_CLIENT (source_object), res, &error);
Packit Service fc05fa
Packit Service fc05fa
	if (success == FALSE) {
Packit Service fc05fa
		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
Packit Service fc05fa
			g_error_free (error);
Packit Service fc05fa
			goto bail;
Packit Service fc05fa
		} else if (g_timer_elapsed (data->timer, NULL) < CONNECT_TIMEOUT) {
Packit Service fc05fa
			g_assert (data->timeout_id == 0);
Packit Service fc05fa
			data->timeout_id = g_timeout_add (500, connect_timeout_cb, data);
Packit Service fc05fa
			g_error_free (error);
Packit Service fc05fa
			return;
Packit Service fc05fa
		}
Packit Service fc05fa
		g_debug ("Failed to connect to device %s", data->device);
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	turn_off_pairing (data->self, data->device);
Packit Service fc05fa
Packit Service fc05fa
	priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (data->self);
Packit Service fc05fa
	g_object_set (G_OBJECT (priv->client),
Packit Service fc05fa
		      "default-adapter-discovering", has_default_adapter (data->self),
Packit Service fc05fa
		      NULL);
Packit Service fc05fa
Packit Service fc05fa
bail:
Packit Service fc05fa
	if (data->timeout_id > 0)
Packit Service fc05fa
		g_source_remove (data->timeout_id);
Packit Service fc05fa
Packit Service fc05fa
	g_free (data->device);
Packit Service fc05fa
	g_timer_destroy (data->timer);
Packit Service fc05fa
	g_free (data);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
create_callback (GObject      *source_object,
Packit Service fc05fa
		 GAsyncResult *res,
Packit Service fc05fa
		 gpointer      user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidget *self = user_data;
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	SetupConnectData *data;
Packit Service fc05fa
	GError *error = NULL;
Packit Service fc05fa
	gboolean ret;
Packit Service fc05fa
	char *path;
Packit Service fc05fa
Packit Service fc05fa
	ret = bluetooth_client_setup_device_finish (BLUETOOTH_CLIENT (source_object),
Packit Service fc05fa
						    res, &path, &error);
Packit Service fc05fa
Packit Service fc05fa
	/* Create failed */
Packit Service fc05fa
	if (ret == FALSE) {
Packit Service fc05fa
		//char *text;
Packit Service fc05fa
		char *dbus_error;
Packit Service fc05fa
Packit Service fc05fa
		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
Packit Service fc05fa
			g_error_free (error);
Packit Service fc05fa
			g_free (path);
Packit Service fc05fa
			return;
Packit Service fc05fa
		}
Packit Service fc05fa
Packit Service fc05fa
		priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (user_data);
Packit Service fc05fa
Packit Service fc05fa
		g_clear_pointer (&priv->pairing_dialog, gtk_widget_destroy);
Packit Service fc05fa
Packit Service fc05fa
		turn_off_pairing (user_data, path);
Packit Service fc05fa
Packit Service fc05fa
		dbus_error = g_dbus_error_get_remote_error (error);
Packit Service fc05fa
		if (g_strcmp0 (dbus_error, "org.bluez.Error.AuthenticationFailed") == 0) {
Packit Service fc05fa
			//FIXME pairing failed because we entered the wrong code
Packit Service fc05fa
		} else if (g_strcmp0 (dbus_error, "org.bluez.Error.AuthenticationCanceled") == 0) {
Packit Service fc05fa
			//FIXME pairing was cancelled
Packit Service fc05fa
		} else {
Packit Service fc05fa
			//FIXME show an error?
Packit Service fc05fa
			/* translators:
Packit Service fc05fa
			 * The “%s” is the device name, for example:
Packit Service fc05fa
			 * Setting up “Sony Bluetooth Headset” failed
Packit Service fc05fa
			 */
Packit Service fc05fa
			//text = g_strdup_printf(_("Setting up “%s” failed"), target_name);
Packit Service fc05fa
Packit Service fc05fa
			g_warning ("Setting up %s failed: %s", path, error->message);
Packit Service fc05fa
Packit Service fc05fa
			//gtk_label_set_markup(GTK_LABEL(label_summary), text);
Packit Service fc05fa
			//g_free (text);
Packit Service fc05fa
		}
Packit Service fc05fa
Packit Service fc05fa
		g_free (dbus_error);
Packit Service fc05fa
		g_error_free (error);
Packit Service fc05fa
		g_free (path);
Packit Service fc05fa
Packit Service fc05fa
		g_object_set (G_OBJECT (priv->client),
Packit Service fc05fa
			      "default-adapter-discovering", has_default_adapter (self),
Packit Service fc05fa
			      NULL);
Packit Service fc05fa
		return;
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (user_data);
Packit Service fc05fa
Packit Service fc05fa
	g_clear_pointer (&priv->pairing_dialog, gtk_widget_destroy);
Packit Service fc05fa
Packit Service fc05fa
	g_hash_table_remove (priv->pairing_devices, path);
Packit Service fc05fa
Packit Service fc05fa
	bluetooth_client_set_trusted (BLUETOOTH_CLIENT (source_object), path, TRUE);
Packit Service fc05fa
Packit Service fc05fa
	data = g_new0 (SetupConnectData, 1);
Packit Service fc05fa
	data->self = user_data;
Packit Service fc05fa
	data->device = path;
Packit Service fc05fa
	data->timer = g_timer_new ();
Packit Service fc05fa
Packit Service fc05fa
	bluetooth_client_connect_service (BLUETOOTH_CLIENT (source_object),
Packit Service fc05fa
					  path, TRUE, priv->cancellable, connect_callback, data);
Packit Service fc05fa
	//gtk_assistant_set_current_page (window_assistant, PAGE_FINISHING);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void start_pairing (BluetoothSettingsWidget *self,
Packit Service fc05fa
			   GtkListBoxRow           *row);
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
device_name_appeared (GObject    *gobject,
Packit Service fc05fa
		      GParamSpec *pspec,
Packit Service fc05fa
		      gpointer    user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	char *name;
Packit Service fc05fa
Packit Service fc05fa
	g_object_get (G_OBJECT (gobject),
Packit Service fc05fa
		      "name", &name,
Packit Service fc05fa
		      NULL);
Packit Service fc05fa
	if (!name)
Packit Service fc05fa
		return;
Packit Service fc05fa
Packit Service fc05fa
	g_debug ("Pairing device name is now '%s'", name);
Packit Service fc05fa
	start_pairing (user_data, GTK_LIST_BOX_ROW (gobject));
Packit Service fc05fa
	g_free (name);
Packit Service fc05fa
Packit Service fc05fa
	g_signal_handlers_disconnect_by_func (gobject, device_name_appeared, user_data);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
start_pairing (BluetoothSettingsWidget *self,
Packit Service fc05fa
	       GtkListBoxRow           *row)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	GDBusProxy *proxy;
Packit Service fc05fa
	gboolean pair = TRUE;
Packit Service fc05fa
	BluetoothType type;
Packit Service fc05fa
	char *bdaddr, *name;
Packit Service fc05fa
	gboolean legacy_pairing;
Packit Service fc05fa
	const char *pincode;
Packit Service fc05fa
Packit Service fc05fa
	g_object_set (G_OBJECT (row), "pairing", TRUE, NULL);
Packit Service fc05fa
	g_object_get (G_OBJECT (row),
Packit Service fc05fa
		      "proxy", &proxy,
Packit Service fc05fa
		      "type", &type,
Packit Service fc05fa
		      "address", &bdaddr,
Packit Service fc05fa
		      "name", &name,
Packit Service fc05fa
		      "legacy-pairing", &legacy_pairing,
Packit Service fc05fa
		      NULL);
Packit Service fc05fa
Packit Service fc05fa
	if (name == NULL) {
Packit Service fc05fa
		g_debug ("No name yet, will start pairing later");
Packit Service fc05fa
		g_signal_connect (G_OBJECT (row), "notify::name",
Packit Service fc05fa
				  G_CALLBACK (device_name_appeared), self);
Packit Service fc05fa
		g_object_unref (proxy);
Packit Service fc05fa
		g_free (bdaddr);
Packit Service fc05fa
		g_free (name);
Packit Service fc05fa
		return;
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	g_debug ("Starting pairing for '%s'", name);
Packit Service fc05fa
Packit Service fc05fa
	/* Legacy pairing might not have been detected yet,
Packit Service fc05fa
	 * so don't check for it */
Packit Service fc05fa
	pincode = get_pincode_for_device (type,
Packit Service fc05fa
					  bdaddr,
Packit Service fc05fa
					  name,
Packit Service fc05fa
					  NULL,
Packit Service fc05fa
					  NULL);
Packit Service fc05fa
	if (g_strcmp0 (pincode, "NULL") == 0)
Packit Service fc05fa
		pair = FALSE;
Packit Service fc05fa
Packit Service fc05fa
	g_debug ("About to setup %s (legacy pairing: %d pair: %d)",
Packit Service fc05fa
		 g_dbus_proxy_get_object_path (proxy),
Packit Service fc05fa
		 legacy_pairing, pair);
Packit Service fc05fa
Packit Service fc05fa
	g_hash_table_insert (priv->pairing_devices,
Packit Service fc05fa
			     g_strdup (g_dbus_proxy_get_object_path (proxy)),
Packit Service fc05fa
			     GINT_TO_POINTER (1));
Packit Service fc05fa
Packit Service fc05fa
	g_object_set (G_OBJECT (priv->client), "default-adapter-discovering", FALSE, NULL);
Packit Service fc05fa
	bluetooth_client_setup_device (priv->client,
Packit Service fc05fa
				       g_dbus_proxy_get_object_path (proxy),
Packit Service fc05fa
				       pair,
Packit Service fc05fa
				       priv->cancellable,
Packit Service fc05fa
				       (GAsyncReadyCallback) create_callback,
Packit Service fc05fa
				       self);
Packit Service fc05fa
	g_object_unref (proxy);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static gboolean
Packit Service fc05fa
switch_connected_state_set (GtkSwitch               *button,
Packit Service fc05fa
			    gboolean                 state,
Packit Service fc05fa
			    BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	ConnectData *data;
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
Packit Service fc05fa
	if (gtk_switch_get_state (button) == state)
Packit Service fc05fa
		return TRUE;
Packit Service fc05fa
Packit Service fc05fa
	if (is_connecting (self, priv->selected_bdaddr))
Packit Service fc05fa
		return TRUE;
Packit Service fc05fa
Packit Service fc05fa
	data = g_new0 (ConnectData, 1);
Packit Service fc05fa
	data->bdaddr = g_strdup (priv->selected_bdaddr);
Packit Service fc05fa
	data->self = self;
Packit Service fc05fa
Packit Service fc05fa
	if (gtk_switch_get_active (button))
Packit Service fc05fa
		g_object_set (G_OBJECT (priv->client),
Packit Service fc05fa
			      "default-adapter-discovering", FALSE,
Packit Service fc05fa
			      NULL);
Packit Service fc05fa
	bluetooth_client_connect_service (priv->client,
Packit Service fc05fa
					  priv->selected_object_path,
Packit Service fc05fa
					  gtk_switch_get_active (button),
Packit Service fc05fa
					  priv->cancellable,
Packit Service fc05fa
					  connect_done,
Packit Service fc05fa
					  data);
Packit Service fc05fa
Packit Service fc05fa
	add_connecting (self, data->bdaddr);
Packit Service fc05fa
	set_connecting_page (self, CONNECTING_NOTEBOOK_PAGE_SPINNER);
Packit Service fc05fa
Packit Service fc05fa
	return TRUE;
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
update_properties (BluetoothSettingsWidget *self,
Packit Service fc05fa
		   GDBusProxy              *proxy)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	GtkSwitch *button;
Packit Service fc05fa
	GtkTreeModel *model;
Packit Service fc05fa
	GtkTreeIter iter;
Packit Service fc05fa
	gboolean ret;
Packit Service fc05fa
	BluetoothType type;
Packit Service fc05fa
	gboolean connected, paired;
Packit Service fc05fa
	char **uuids, *bdaddr, *name, *icon;
Packit Service fc05fa
	guint i;
Packit Service fc05fa
Packit Service fc05fa
	model = bluetooth_client_get_device_model (priv->client);
Packit Service fc05fa
	g_assert (model);
Packit Service fc05fa
Packit Service fc05fa
	ret = gtk_tree_model_get_iter_first (model, &iter);
Packit Service fc05fa
	while (ret) {
Packit Service fc05fa
		GDBusProxy *p;
Packit Service fc05fa
Packit Service fc05fa
		gtk_tree_model_get (model, &iter,
Packit Service fc05fa
				    BLUETOOTH_COLUMN_PROXY, &p,
Packit Service fc05fa
				    -1);
Packit Service fc05fa
Packit Service fc05fa
		if (g_strcmp0 (g_dbus_proxy_get_object_path (proxy),
Packit Service fc05fa
			       g_dbus_proxy_get_object_path (p)) == 0) {
Packit Service fc05fa
			g_object_unref (p);
Packit Service fc05fa
			break;
Packit Service fc05fa
		}
Packit Service fc05fa
Packit Service fc05fa
		g_object_unref (p);
Packit Service fc05fa
Packit Service fc05fa
		ret = gtk_tree_model_iter_next (model, &iter);
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	/* This means we've found the device */
Packit Service fc05fa
	g_assert (ret);
Packit Service fc05fa
Packit Service fc05fa
	gtk_tree_model_get (model, &iter,
Packit Service fc05fa
			    BLUETOOTH_COLUMN_ADDRESS, &bdaddr,
Packit Service fc05fa
			    BLUETOOTH_COLUMN_NAME, &name,
Packit Service fc05fa
			    BLUETOOTH_COLUMN_ICON, &icon,
Packit Service fc05fa
			    BLUETOOTH_COLUMN_PAIRED, &paired,
Packit Service fc05fa
			    BLUETOOTH_COLUMN_CONNECTED, &connected,
Packit Service fc05fa
			    BLUETOOTH_COLUMN_UUIDS, &uuids,
Packit Service fc05fa
			    BLUETOOTH_COLUMN_TYPE, &type,
Packit Service fc05fa
			    -1);
Packit Service fc05fa
	if (priv->debug)
Packit Service fc05fa
		bluetooth_client_dump_device (model, &iter);
Packit Service fc05fa
	g_object_unref (model);
Packit Service fc05fa
Packit Service fc05fa
	g_free (priv->selected_object_path);
Packit Service fc05fa
	priv->selected_object_path = g_strdup (g_dbus_proxy_get_object_path (proxy));
Packit Service fc05fa
Packit Service fc05fa
	/* Hide all the buttons now, and show them again if we need to */
Packit Service fc05fa
	gtk_widget_hide (WID ("keyboard_button"));
Packit Service fc05fa
	gtk_widget_hide (WID ("sound_button"));
Packit Service fc05fa
	gtk_widget_hide (WID ("mouse_button"));
Packit Service fc05fa
	gtk_widget_hide (WID ("send_button"));
Packit Service fc05fa
Packit Service fc05fa
	/* Name */
Packit Service fc05fa
	gtk_window_set_title (GTK_WINDOW (priv->properties_dialog), name);
Packit Service fc05fa
	g_free (priv->selected_name);
Packit Service fc05fa
	priv->selected_name = name;
Packit Service fc05fa
Packit Service fc05fa
	/* Icon */
Packit Service fc05fa
	gtk_image_set_from_icon_name (GTK_IMAGE (WID ("image")), icon, GTK_ICON_SIZE_DIALOG);
Packit Service fc05fa
Packit Service fc05fa
	/* Connection */
Packit Service fc05fa
	button = GTK_SWITCH (WID ("switch_connection"));
Packit Service fc05fa
Packit Service fc05fa
	gtk_switch_set_state (button, connected);
Packit Service fc05fa
	if (is_connecting (self, bdaddr)) {
Packit Service fc05fa
		set_connecting_page (self, CONNECTING_NOTEBOOK_PAGE_SPINNER);
Packit Service fc05fa
	} else {
Packit Service fc05fa
		set_connecting_page (self, CONNECTING_NOTEBOOK_PAGE_SWITCH);
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	/* Paired */
Packit Service fc05fa
	gtk_label_set_text (GTK_LABEL (WID ("paired_label")),
Packit Service fc05fa
			    paired ? _("Yes") : _("No"));
Packit Service fc05fa
Packit Service fc05fa
	/* UUIDs */
Packit Service fc05fa
	gtk_widget_set_sensitive (GTK_WIDGET (button),
Packit Service fc05fa
				  bluetooth_client_get_connectable ((const char **) uuids));
Packit Service fc05fa
	for (i = 0; uuids && uuids[i] != NULL; i++) {
Packit Service fc05fa
		if (g_str_equal (uuids[i], "OBEXObjectPush")) {
Packit Service fc05fa
			gtk_widget_show (WID ("send_button"));
Packit Service fc05fa
			break;
Packit Service fc05fa
		}
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	/* Type */
Packit Service fc05fa
	gtk_label_set_text (GTK_LABEL (WID ("type_label")), bluetooth_type_to_string (type));
Packit Service fc05fa
	switch (type) {
Packit Service fc05fa
	case BLUETOOTH_TYPE_KEYBOARD:
Packit Service fc05fa
		gtk_widget_show (WID ("keyboard_button"));
Packit Service fc05fa
		break;
Packit Service fc05fa
	case BLUETOOTH_TYPE_MOUSE:
Packit Service fc05fa
	case BLUETOOTH_TYPE_TABLET:
Packit Service fc05fa
		gtk_widget_show (WID ("mouse_button"));
Packit Service fc05fa
		break;
Packit Service fc05fa
	case BLUETOOTH_TYPE_HEADSET:
Packit Service fc05fa
	case BLUETOOTH_TYPE_HEADPHONES:
Packit Service fc05fa
	case BLUETOOTH_TYPE_OTHER_AUDIO:
Packit Service fc05fa
		gtk_widget_show (WID ("sound_button"));
Packit Service fc05fa
	default:
Packit Service fc05fa
		/* others? */
Packit Service fc05fa
		;
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	/* Address */
Packit Service fc05fa
	gtk_label_set_text (GTK_LABEL (WID ("address_label")), bdaddr);
Packit Service fc05fa
Packit Service fc05fa
	g_free (priv->selected_bdaddr);
Packit Service fc05fa
	priv->selected_bdaddr = bdaddr;
Packit Service fc05fa
Packit Service fc05fa
	g_free (icon);
Packit Service fc05fa
	g_strfreev (uuids);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
switch_panel (BluetoothSettingsWidget *self,
Packit Service fc05fa
	      const char       *panel)
Packit Service fc05fa
{
Packit Service fc05fa
	g_signal_emit (G_OBJECT (self),
Packit Service fc05fa
		       signals[PANEL_CHANGED],
Packit Service fc05fa
		       0, panel);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static gboolean
Packit Service fc05fa
keyboard_callback (GtkButton        *button,
Packit Service fc05fa
		   BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	switch_panel (self, KEYBOARD_PREFS);
Packit Service fc05fa
	return TRUE;
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static gboolean
Packit Service fc05fa
mouse_callback (GtkButton        *button,
Packit Service fc05fa
		BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	switch_panel (self, MOUSE_PREFS);
Packit Service fc05fa
	return TRUE;
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static gboolean
Packit Service fc05fa
sound_callback (GtkButton        *button,
Packit Service fc05fa
		BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	switch_panel (self, SOUND_PREFS);
Packit Service fc05fa
	return TRUE;
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
send_callback (GtkButton        *button,
Packit Service fc05fa
	       BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	bluetooth_send_to_address (priv->selected_bdaddr, priv->selected_name);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
/* Visibility/Discoverable */
Packit Service fc05fa
static void
Packit Service fc05fa
update_visibility (BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	char *name;
Packit Service fc05fa
Packit Service fc05fa
	g_object_get (G_OBJECT (priv->client), "default-adapter-name", &name, NULL);
Packit Service fc05fa
	if (name != NULL) {
Packit Service fc05fa
		char *label, *path, *uri;
Packit Service fc05fa
Packit Service fc05fa
		path = lookup_download_dir ();
Packit Service fc05fa
		uri = g_filename_to_uri (path, NULL, NULL);
Packit Service fc05fa
		g_free (path);
Packit Service fc05fa
Packit Service fc05fa
		/* translators: first %s is the name of the computer, for example:
Packit Service fc05fa
		 * Visible as “Bastien Nocera’s Computer” followed by the
Packit Service fc05fa
		 * location of the Downloads folder.*/
Packit Service fc05fa
		label = g_strdup_printf (_("Visible as “%s” and available for Bluetooth file transfers. Transferred files are placed in the Downloads folder."), name, uri);
Packit Service fc05fa
		g_free (uri);
Packit Service fc05fa
		g_free (name);
Packit Service fc05fa
		gtk_label_set_markup (GTK_LABEL (priv->visible_label), label);
Packit Service fc05fa
		g_free (label);
Packit Service fc05fa
	}
Packit Service fc05fa
	gtk_widget_set_visible (priv->visible_label, name != NULL);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
name_changed (BluetoothClient  *client,
Packit Service fc05fa
	      GParamSpec       *spec,
Packit Service fc05fa
	      BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	update_visibility (self);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static gboolean
Packit Service fc05fa
show_confirm_dialog (BluetoothSettingsWidget *self,
Packit Service fc05fa
		     const char *name)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	GtkWidget *dialog;
Packit Service fc05fa
	gint response;
Packit Service fc05fa
Packit Service fc05fa
	dialog = gtk_message_dialog_new (GTK_WINDOW (priv->properties_dialog), GTK_DIALOG_MODAL,
Packit Service fc05fa
					 GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
Packit Service fc05fa
					 _("Remove “%s” from the list of devices?"), name);
Packit Service fc05fa
	g_object_set (G_OBJECT (dialog), "secondary-text",
Packit Service fc05fa
		      _("If you remove the device, you will have to set it up again before next use."),
Packit Service fc05fa
		      NULL);
Packit Service fc05fa
Packit Service fc05fa
	gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Cancel"), GTK_RESPONSE_CANCEL);
Packit Service fc05fa
	gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Remove"), GTK_RESPONSE_ACCEPT);
Packit Service fc05fa
Packit Service fc05fa
	response = gtk_dialog_run (GTK_DIALOG (dialog));
Packit Service fc05fa
Packit Service fc05fa
	gtk_widget_destroy (dialog);
Packit Service fc05fa
Packit Service fc05fa
	if (response == GTK_RESPONSE_ACCEPT)
Packit Service fc05fa
		return TRUE;
Packit Service fc05fa
Packit Service fc05fa
	return FALSE;
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static gboolean
Packit Service fc05fa
remove_selected_device (BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	GDBusProxy *adapter_proxy;
Packit Service fc05fa
	GError *error = NULL;
Packit Service fc05fa
	GVariant *ret;
Packit Service fc05fa
Packit Service fc05fa
	g_debug ("About to call RemoveDevice for %s", priv->selected_object_path);
Packit Service fc05fa
Packit Service fc05fa
	adapter_proxy = _bluetooth_client_get_default_adapter (priv->client);
Packit Service fc05fa
Packit Service fc05fa
	if (adapter_proxy == NULL) {
Packit Service fc05fa
		g_warning ("Failed to get a GDBusProxy for the default adapter");
Packit Service fc05fa
		return FALSE;
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	//FIXME use adapter1_call_remove_device_sync()
Packit Service fc05fa
	ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (adapter_proxy),
Packit Service fc05fa
				      "RemoveDevice",
Packit Service fc05fa
				      g_variant_new ("(o)", priv->selected_object_path),
Packit Service fc05fa
				      G_DBUS_CALL_FLAGS_NONE,
Packit Service fc05fa
				      -1,
Packit Service fc05fa
				      NULL,
Packit Service fc05fa
				      &error);
Packit Service fc05fa
Packit Service fc05fa
	if (ret == NULL) {
Packit Service fc05fa
		g_warning ("Failed to remove device '%s': %s",
Packit Service fc05fa
			   priv->selected_object_path, error->message);
Packit Service fc05fa
		g_error_free (error);
Packit Service fc05fa
	} else {
Packit Service fc05fa
		g_variant_unref (ret);
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	g_object_unref (adapter_proxy);
Packit Service fc05fa
Packit Service fc05fa
	return (ret != NULL);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
delete_clicked (GtkButton        *button,
Packit Service fc05fa
		BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	if (show_confirm_dialog (self, priv->selected_name) != FALSE) {
Packit Service fc05fa
		remove_selected_device (self);
Packit Service fc05fa
		gtk_widget_hide (priv->properties_dialog);
Packit Service fc05fa
	}
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
default_adapter_changed (BluetoothClient  *client,
Packit Service fc05fa
			 GParamSpec       *spec,
Packit Service fc05fa
			 BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	g_autofree char *default_adapter = NULL;
Packit Service fc05fa
Packit Service fc05fa
	g_object_get (priv->client, "default-adapter", &default_adapter, NULL);
Packit Service fc05fa
Packit Service fc05fa
	g_debug ("Default adapter changed to: %s", default_adapter ? default_adapter : "(none)");
Packit Service fc05fa
Packit Service fc05fa
	g_object_set (G_OBJECT (client), "default-adapter-discovering", default_adapter != NULL, NULL);
Packit Service fc05fa
	g_object_set (G_OBJECT (client), "default-adapter-discoverable", default_adapter != NULL, NULL);
Packit Service fc05fa
Packit Service fc05fa
	g_signal_emit (G_OBJECT (self), signals[ADAPTER_STATUS_CHANGED], 0);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static gint
Packit Service fc05fa
device_sort_func (gconstpointer a, gconstpointer b, gpointer data)
Packit Service fc05fa
{
Packit Service fc05fa
	GObject *row_a = (GObject*)a;
Packit Service fc05fa
	GObject *row_b = (GObject*)b;
Packit Service fc05fa
	gboolean setup_a, setup_b;
Packit Service fc05fa
	gboolean paired_a, paired_b;
Packit Service fc05fa
	gboolean trusted_a, trusted_b;
Packit Service fc05fa
	gboolean connected_a, connected_b;
Packit Service fc05fa
	char *name_a, *name_b;
Packit Service fc05fa
	int ret;
Packit Service fc05fa
Packit Service fc05fa
	g_object_get (row_a,
Packit Service fc05fa
		      "paired", &paired_a,
Packit Service fc05fa
		      "trusted", &trusted_a,
Packit Service fc05fa
		      "connected", &connected_a,
Packit Service fc05fa
		      "name", &name_a,
Packit Service fc05fa
		      NULL);
Packit Service fc05fa
	g_object_get (row_b,
Packit Service fc05fa
		      "paired", &paired_b,
Packit Service fc05fa
		      "trusted", &trusted_b,
Packit Service fc05fa
		      "connected", &connected_b,
Packit Service fc05fa
		      "name", &name_b,
Packit Service fc05fa
		      NULL);
Packit Service fc05fa
Packit Service fc05fa
	/* First, paired or trusted devices (setup devices) */
Packit Service fc05fa
	setup_a = paired_a || trusted_a;
Packit Service fc05fa
	setup_b = paired_b || trusted_b;
Packit Service fc05fa
	if (setup_a != setup_b) {
Packit Service fc05fa
		if (setup_a)
Packit Service fc05fa
			ret = -1;
Packit Service fc05fa
		else
Packit Service fc05fa
			ret = 1;
Packit Service fc05fa
		goto out;
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	/* Then connected ones */
Packit Service fc05fa
	if (connected_a != connected_b) {
Packit Service fc05fa
		if (connected_a)
Packit Service fc05fa
			ret = -1;
Packit Service fc05fa
		else
Packit Service fc05fa
			ret = 1;
Packit Service fc05fa
		goto out;
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	if (name_a == NULL) {
Packit Service fc05fa
		ret = 1;
Packit Service fc05fa
		goto out;
Packit Service fc05fa
	}
Packit Service fc05fa
	if (name_b == NULL) {
Packit Service fc05fa
		ret = -1;
Packit Service fc05fa
		goto out;
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	/* And all being equal, alphabetically */
Packit Service fc05fa
	ret = g_utf8_collate (name_a, name_b);
Packit Service fc05fa
Packit Service fc05fa
out:
Packit Service fc05fa
	g_free (name_a);
Packit Service fc05fa
	g_free (name_b);
Packit Service fc05fa
	return ret;
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
update_header_func (GtkListBoxRow  *row,
Packit Service fc05fa
		    GtkListBoxRow  *before,
Packit Service fc05fa
		    gpointer    user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	GtkWidget *current;
Packit Service fc05fa
Packit Service fc05fa
	if (before == NULL)
Packit Service fc05fa
		return;
Packit Service fc05fa
Packit Service fc05fa
	current = gtk_list_box_row_get_header (row);
Packit Service fc05fa
	if (current == NULL) {
Packit Service fc05fa
		current = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
Packit Service fc05fa
		gtk_widget_show (current);
Packit Service fc05fa
		gtk_list_box_row_set_header (row, current);
Packit Service fc05fa
	}
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static gboolean
Packit Service fc05fa
keynav_failed (GtkWidget *list, GtkDirectionType direction, BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	GList *children, *item;
Packit Service fc05fa
Packit Service fc05fa
	children = gtk_container_get_children (GTK_CONTAINER (priv->device_list));
Packit Service fc05fa
Packit Service fc05fa
	if (direction == GTK_DIR_DOWN) {
Packit Service fc05fa
		item = children;
Packit Service fc05fa
	} else {
Packit Service fc05fa
		item = g_list_last (children);
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	gtk_widget_child_focus (item->data, direction);
Packit Service fc05fa
Packit Service fc05fa
	g_list_free (children);
Packit Service fc05fa
Packit Service fc05fa
	return TRUE;
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
activate_row (BluetoothSettingsWidget *self,
Packit Service fc05fa
              GtkListBoxRow    *row)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	GtkWidget *w;
Packit Service fc05fa
	GtkWidget *toplevel;
Packit Service fc05fa
	gboolean paired, trusted, is_setup;
Packit Service fc05fa
Packit Service fc05fa
	g_object_get (G_OBJECT (row),
Packit Service fc05fa
		      "paired", &paired,
Packit Service fc05fa
		      "trusted", &trusted,
Packit Service fc05fa
		      NULL);
Packit Service fc05fa
	is_setup = paired || trusted;
Packit Service fc05fa
Packit Service fc05fa
	if (is_setup) {
Packit Service fc05fa
		GDBusProxy *proxy;
Packit Service fc05fa
Packit Service fc05fa
		//FIXME pass the row
Packit Service fc05fa
		//FIXME add UUIDs to the row
Packit Service fc05fa
		//FIXME add icon to the row
Packit Service fc05fa
		g_object_get (G_OBJECT (row), "proxy", &proxy, NULL);
Packit Service fc05fa
		update_properties (self, proxy);
Packit Service fc05fa
		g_object_unref (proxy);
Packit Service fc05fa
Packit Service fc05fa
		w = priv->properties_dialog;
Packit Service fc05fa
		toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self));
Packit Service fc05fa
		gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (toplevel));
Packit Service fc05fa
		gtk_window_set_modal (GTK_WINDOW (w), TRUE);
Packit Service fc05fa
		gtk_window_present (GTK_WINDOW (w));
Packit Service fc05fa
	} else {
Packit Service fc05fa
		start_pairing (self, row);
Packit Service fc05fa
	}
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
add_device_section (BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	GtkWidget *vbox;
Packit Service fc05fa
	GtkWidget *box, *hbox, *spinner;
Packit Service fc05fa
	GtkWidget *frame, *label;
Packit Service fc05fa
	gchar *s;
Packit Service fc05fa
Packit Service fc05fa
	vbox = WID ("vbox_bluetooth");
Packit Service fc05fa
Packit Service fc05fa
	box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
Packit Service fc05fa
	gtk_widget_set_margin_top (box, 6);
Packit Service fc05fa
	gtk_box_pack_start (GTK_BOX (vbox), box, TRUE, TRUE, 0);
Packit Service fc05fa
	priv->child_box = box;
Packit Service fc05fa
Packit Service fc05fa
	hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
Packit Service fc05fa
	gtk_box_pack_start (GTK_BOX (box), hbox, FALSE, TRUE, 0);
Packit Service fc05fa
Packit Service fc05fa
	s = g_markup_printf_escaped ("%s", _("Devices"));
Packit Service fc05fa
	priv->device_label = gtk_label_new (s);
Packit Service fc05fa
	g_free (s);
Packit Service fc05fa
	gtk_label_set_use_markup (GTK_LABEL (priv->device_label), TRUE);
Packit Service fc05fa
	gtk_misc_set_alignment (GTK_MISC (priv->device_label), 0, 0.5);
Packit Service fc05fa
	gtk_widget_set_margin_end (priv->device_label, 6);
Packit Service fc05fa
	gtk_widget_set_margin_bottom (priv->device_label, 12);
Packit Service fc05fa
	gtk_box_pack_start (GTK_BOX (hbox), priv->device_label, FALSE, TRUE, 0);
Packit Service fc05fa
Packit Service fc05fa
	/* Discoverable spinner */
Packit Service fc05fa
	priv->device_spinner = spinner = gtk_spinner_new ();
Packit Service fc05fa
	g_object_bind_property (G_OBJECT (priv->client), "default-adapter-discovering",
Packit Service fc05fa
				G_OBJECT (priv->device_spinner), "active",
Packit Service fc05fa
				G_BINDING_SYNC_CREATE);
Packit Service fc05fa
	gtk_widget_set_margin_bottom (spinner, 12);
Packit Service fc05fa
	gtk_box_pack_start (GTK_BOX (hbox), spinner, FALSE, TRUE, 0);
Packit Service fc05fa
Packit Service fc05fa
	/* Discoverable label placeholder, the real name is set in update_visibility().
Packit Service fc05fa
	 * If you ever see this string during normal use, please file a bug. */
Packit Service fc05fa
	priv->visible_label = WID ("explanation-label");
Packit Service fc05fa
	gtk_label_set_use_markup (GTK_LABEL (priv->visible_label), TRUE);
Packit Service fc05fa
	update_visibility (self);
Packit Service fc05fa
Packit Service fc05fa
	priv->device_list = gtk_list_box_new ();
Packit Service fc05fa
	g_signal_connect (priv->device_list, "keynav-failed", G_CALLBACK (keynav_failed), self);
Packit Service fc05fa
	gtk_list_box_set_selection_mode (GTK_LIST_BOX (priv->device_list), GTK_SELECTION_NONE);
Packit Service fc05fa
	gtk_list_box_set_header_func (GTK_LIST_BOX (priv->device_list),
Packit Service fc05fa
				      update_header_func,
Packit Service fc05fa
				      NULL, NULL);
Packit Service fc05fa
	gtk_list_box_set_sort_func (GTK_LIST_BOX (priv->device_list),
Packit Service fc05fa
				    (GtkListBoxSortFunc)device_sort_func, NULL, NULL);
Packit Service fc05fa
	g_signal_connect_swapped (priv->device_list, "row-activated",
Packit Service fc05fa
				  G_CALLBACK (activate_row), self);
Packit Service fc05fa
        atk_object_add_relationship (ATK_OBJECT (gtk_widget_get_accessible (priv->device_label)),
Packit Service fc05fa
                                     ATK_RELATION_LABEL_FOR,
Packit Service fc05fa
                                     ATK_OBJECT (gtk_widget_get_accessible (priv->device_list)));
Packit Service fc05fa
        atk_object_add_relationship (ATK_OBJECT (gtk_widget_get_accessible (priv->device_list)),
Packit Service fc05fa
                                     ATK_RELATION_LABELLED_BY,
Packit Service fc05fa
                                     ATK_OBJECT (gtk_widget_get_accessible (priv->device_label)));
Packit Service fc05fa
Packit Service fc05fa
	priv->device_stack = gtk_stack_new ();
Packit Service fc05fa
	gtk_stack_set_homogeneous (GTK_STACK (priv->device_stack), FALSE);
Packit Service fc05fa
Packit Service fc05fa
	label = gtk_label_new (_("Searching for devices…"));
Packit Service fc05fa
	gtk_style_context_add_class (gtk_widget_get_style_context (label), "dim-label");
Packit Service fc05fa
	gtk_stack_add_named (GTK_STACK (priv->device_stack), label, FILLER_PAGE);
Packit Service fc05fa
Packit Service fc05fa
	frame = gtk_frame_new (NULL);
Packit Service fc05fa
	gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
Packit Service fc05fa
	gtk_container_add (GTK_CONTAINER (frame), priv->device_list);
Packit Service fc05fa
	gtk_stack_add_named (GTK_STACK (priv->device_stack), frame, DEVICES_PAGE);
Packit Service fc05fa
	gtk_box_pack_start (GTK_BOX (box), priv->device_stack, TRUE, TRUE, 0);
Packit Service fc05fa
Packit Service fc05fa
	gtk_widget_show_all (box);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static gboolean
Packit Service fc05fa
is_interesting_device (GtkTreeModel *model,
Packit Service fc05fa
		       GtkTreeIter  *iter)
Packit Service fc05fa
{
Packit Service fc05fa
	GtkTreeIter parent_iter;
Packit Service fc05fa
	gboolean is_default;
Packit Service fc05fa
Packit Service fc05fa
	/* Not a child */
Packit Service fc05fa
	if (gtk_tree_model_iter_parent (model, &parent_iter, iter) == FALSE)
Packit Service fc05fa
		return FALSE;
Packit Service fc05fa
Packit Service fc05fa
	/* Not the default adapter */
Packit Service fc05fa
	gtk_tree_model_get (model, &parent_iter,
Packit Service fc05fa
			    BLUETOOTH_COLUMN_DEFAULT, &is_default,
Packit Service fc05fa
			    -1);
Packit Service fc05fa
	return is_default;
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
row_inserted_cb (GtkTreeModel *tree_model,
Packit Service fc05fa
		 GtkTreePath  *path,
Packit Service fc05fa
		 GtkTreeIter  *iter,
Packit Service fc05fa
		 gpointer      user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidget *self = user_data;
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (user_data);
Packit Service fc05fa
	GDBusProxy *proxy;
Packit Service fc05fa
	char *name, *bdaddr;
Packit Service fc05fa
	BluetoothType type;
Packit Service fc05fa
	gboolean paired, trusted, connected, legacy_pairing;
Packit Service fc05fa
	GtkWidget *row;
Packit Service fc05fa
Packit Service fc05fa
	if (is_interesting_device (tree_model, iter) == FALSE) {
Packit Service fc05fa
		gtk_tree_model_get (tree_model, iter,
Packit Service fc05fa
				    BLUETOOTH_COLUMN_NAME, &name,
Packit Service fc05fa
				    -1);
Packit Service fc05fa
		g_debug ("Not adding device '%s'", name);
Packit Service fc05fa
		g_free (name);
Packit Service fc05fa
		return;
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	gtk_tree_model_get (tree_model, iter,
Packit Service fc05fa
			    BLUETOOTH_COLUMN_PROXY, &proxy,
Packit Service fc05fa
			    BLUETOOTH_COLUMN_NAME, &name,
Packit Service fc05fa
			    BLUETOOTH_COLUMN_PAIRED, &paired,
Packit Service fc05fa
			    BLUETOOTH_COLUMN_TRUSTED, &trusted,
Packit Service fc05fa
			    BLUETOOTH_COLUMN_CONNECTED, &connected,
Packit Service fc05fa
			    BLUETOOTH_COLUMN_ADDRESS, &bdaddr,
Packit Service fc05fa
			    BLUETOOTH_COLUMN_TYPE, &type,
Packit Service fc05fa
			    BLUETOOTH_COLUMN_LEGACYPAIRING, &legacy_pairing,
Packit Service fc05fa
			    -1);
Packit Service fc05fa
Packit Service fc05fa
	g_debug ("Adding device %s (%s)", name, g_dbus_proxy_get_object_path (proxy));
Packit Service fc05fa
Packit Service fc05fa
	add_device_type (self, bdaddr, type);
Packit Service fc05fa
Packit Service fc05fa
	row = g_object_new (BLUETOOTH_TYPE_SETTINGS_ROW,
Packit Service fc05fa
			    "proxy", proxy,
Packit Service fc05fa
			    "paired", paired,
Packit Service fc05fa
			    "trusted", trusted,
Packit Service fc05fa
			    "type", type,
Packit Service fc05fa
			    "connected", connected,
Packit Service fc05fa
			    "name", name,
Packit Service fc05fa
			    "address", bdaddr,
Packit Service fc05fa
			    "legacy-pairing", legacy_pairing,
Packit Service fc05fa
			    NULL);
Packit Service fc05fa
	g_object_set_data_full (G_OBJECT (row), "object-path", g_strdup (g_dbus_proxy_get_object_path (proxy)), g_free);
Packit Service fc05fa
Packit Service fc05fa
	gtk_container_add (GTK_CONTAINER (priv->device_list), row);
Packit Service fc05fa
	gtk_size_group_add_widget (priv->row_sizegroup, row);
Packit Service fc05fa
Packit Service fc05fa
	g_object_unref (proxy);
Packit Service fc05fa
	g_free (name);
Packit Service fc05fa
	g_free (bdaddr);
Packit Service fc05fa
Packit Service fc05fa
	gtk_stack_set_transition_type (GTK_STACK (priv->device_stack),
Packit Service fc05fa
				       GTK_STACK_TRANSITION_TYPE_SLIDE_DOWN);
Packit Service fc05fa
	gtk_container_child_set (GTK_CONTAINER (WID ("vbox_bluetooth")),
Packit Service fc05fa
				 priv->child_box, "expand", FALSE, NULL);
Packit Service fc05fa
	gtk_stack_set_visible_child_name (GTK_STACK (priv->device_stack), DEVICES_PAGE);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
row_changed_cb (GtkTreeModel *tree_model,
Packit Service fc05fa
		GtkTreePath  *path,
Packit Service fc05fa
		GtkTreeIter  *iter,
Packit Service fc05fa
		gpointer      user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidget *self = user_data;
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (user_data);
Packit Service fc05fa
	GDBusProxy *proxy;
Packit Service fc05fa
	GList *l, *children;
Packit Service fc05fa
	const char *object_path;
Packit Service fc05fa
Packit Service fc05fa
	if (is_interesting_device (tree_model, iter) == FALSE) {
Packit Service fc05fa
		char *name;
Packit Service fc05fa
Packit Service fc05fa
		gtk_tree_model_get (tree_model, iter,
Packit Service fc05fa
				    BLUETOOTH_COLUMN_NAME, &name,
Packit Service fc05fa
				    -1);
Packit Service fc05fa
		g_debug ("Not interested in device '%s'", name);
Packit Service fc05fa
		g_free (name);
Packit Service fc05fa
		return;
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	gtk_tree_model_get (tree_model, iter,
Packit Service fc05fa
			    BLUETOOTH_COLUMN_PROXY, &proxy,
Packit Service fc05fa
			    -1);
Packit Service fc05fa
	object_path = g_dbus_proxy_get_object_path (proxy);
Packit Service fc05fa
Packit Service fc05fa
	children = gtk_container_get_children (GTK_CONTAINER (priv->device_list));
Packit Service fc05fa
	for (l = children; l != NULL; l = l->next) {
Packit Service fc05fa
		const char *path;
Packit Service fc05fa
Packit Service fc05fa
		path = g_object_get_data (G_OBJECT (l->data), "object-path");
Packit Service fc05fa
		if (g_str_equal (object_path, path)) {
Packit Service fc05fa
			g_autofree char *name = NULL;
Packit Service fc05fa
			g_autofree char *bdaddr = NULL;
Packit Service fc05fa
			BluetoothType type;
Packit Service fc05fa
			gboolean paired, trusted, connected, legacy_pairing;
Packit Service fc05fa
Packit Service fc05fa
			gtk_tree_model_get (tree_model, iter,
Packit Service fc05fa
					    BLUETOOTH_COLUMN_NAME, &name,
Packit Service fc05fa
					    BLUETOOTH_COLUMN_PAIRED, &paired,
Packit Service fc05fa
					    BLUETOOTH_COLUMN_TRUSTED, &trusted,
Packit Service fc05fa
					    BLUETOOTH_COLUMN_CONNECTED, &connected,
Packit Service fc05fa
					    BLUETOOTH_COLUMN_ADDRESS, &bdaddr,
Packit Service fc05fa
					    BLUETOOTH_COLUMN_TYPE, &type,
Packit Service fc05fa
					    BLUETOOTH_COLUMN_LEGACYPAIRING, &legacy_pairing,
Packit Service fc05fa
					    -1);
Packit Service fc05fa
Packit Service fc05fa
			add_device_type (self, bdaddr, type);
Packit Service fc05fa
Packit Service fc05fa
			g_object_set (G_OBJECT (l->data),
Packit Service fc05fa
				      "paired", paired,
Packit Service fc05fa
				      "trusted", trusted,
Packit Service fc05fa
				      "type", type,
Packit Service fc05fa
				      "connected", connected,
Packit Service fc05fa
				      "name", name,
Packit Service fc05fa
				      "legacy-pairing", legacy_pairing,
Packit Service fc05fa
				      NULL);
Packit Service fc05fa
Packit Service fc05fa
			/* Update the properties if necessary */
Packit Service fc05fa
			if (g_strcmp0 (priv->selected_object_path, object_path) == 0)
Packit Service fc05fa
				update_properties (user_data, proxy);
Packit Service fc05fa
			break;
Packit Service fc05fa
		}
Packit Service fc05fa
	}
Packit Service fc05fa
	g_list_free (children);
Packit Service fc05fa
	g_object_unref (proxy);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
device_removed_cb (BluetoothClient *client,
Packit Service fc05fa
		   const char      *object_path,
Packit Service fc05fa
		   gpointer         user_data)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (user_data);
Packit Service fc05fa
	GList *children, *l;
Packit Service fc05fa
	gboolean found = FALSE;
Packit Service fc05fa
Packit Service fc05fa
	children = gtk_container_get_children (GTK_CONTAINER (priv->device_list));
Packit Service fc05fa
	for (l = children; l != NULL; l = l->next) {
Packit Service fc05fa
		const char *path;
Packit Service fc05fa
Packit Service fc05fa
		path = g_object_get_data (G_OBJECT (l->data), "object-path");
Packit Service fc05fa
		if (g_str_equal (path, object_path)) {
Packit Service fc05fa
			char *name;
Packit Service fc05fa
Packit Service fc05fa
			g_object_get (G_OBJECT (l->data), "name", &name, NULL);
Packit Service fc05fa
			g_debug ("Removing device '%s'", name);
Packit Service fc05fa
			g_free (name);
Packit Service fc05fa
Packit Service fc05fa
			gtk_widget_destroy (GTK_WIDGET (l->data));
Packit Service fc05fa
			found = TRUE;
Packit Service fc05fa
			break;
Packit Service fc05fa
		}
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	if (found) {
Packit Service fc05fa
		if (gtk_container_get_children (GTK_CONTAINER (priv->device_list)) == NULL) {
Packit Service fc05fa
			gtk_stack_set_transition_type (GTK_STACK (priv->device_stack),
Packit Service fc05fa
						       GTK_STACK_TRANSITION_TYPE_NONE);
Packit Service fc05fa
			gtk_container_child_set (GTK_CONTAINER (WID ("vbox_bluetooth")),
Packit Service fc05fa
						 priv->child_box, "expand", TRUE, NULL);
Packit Service fc05fa
			gtk_stack_set_visible_child_name (GTK_STACK (priv->device_stack), FILLER_PAGE);
Packit Service fc05fa
		}
Packit Service fc05fa
	} else {
Packit Service fc05fa
		g_debug ("Didn't find a row to remove for tree path %s", object_path);
Packit Service fc05fa
	}
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
setup_properties_dialog (BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	GtkWidget *container;
Packit Service fc05fa
	GtkStyleContext *context;
Packit Service fc05fa
Packit Service fc05fa
	priv->properties_dialog = g_object_new (GTK_TYPE_DIALOG, "use-header-bar", TRUE, NULL);
Packit Service fc05fa
	gtk_widget_set_size_request (priv->properties_dialog, 380, -1);
Packit Service fc05fa
	gtk_window_set_resizable (GTK_WINDOW (priv->properties_dialog), FALSE);
Packit Service fc05fa
	container = gtk_dialog_get_content_area (GTK_DIALOG (priv->properties_dialog));
Packit Service fc05fa
	gtk_container_add (GTK_CONTAINER (container), WID ("properties_vbox"));
Packit Service fc05fa
Packit Service fc05fa
	g_signal_connect (G_OBJECT (priv->properties_dialog), "delete-event",
Packit Service fc05fa
			  G_CALLBACK (gtk_widget_hide_on_delete), NULL);
Packit Service fc05fa
	g_signal_connect (G_OBJECT (WID ("delete_button")), "clicked",
Packit Service fc05fa
			  G_CALLBACK (delete_clicked), self);
Packit Service fc05fa
	g_signal_connect (G_OBJECT (WID ("mouse_button")), "clicked",
Packit Service fc05fa
			  G_CALLBACK (mouse_callback), self);
Packit Service fc05fa
	g_signal_connect (G_OBJECT (WID ("keyboard_button")), "clicked",
Packit Service fc05fa
			  G_CALLBACK (keyboard_callback), self);
Packit Service fc05fa
	g_signal_connect (G_OBJECT (WID ("sound_button")), "clicked",
Packit Service fc05fa
			  G_CALLBACK (sound_callback), self);
Packit Service fc05fa
	g_signal_connect (G_OBJECT (WID ("send_button")), "clicked",
Packit Service fc05fa
			  G_CALLBACK (send_callback), self);
Packit Service fc05fa
	g_signal_connect (G_OBJECT (WID ("switch_connection")), "state-set",
Packit Service fc05fa
			  G_CALLBACK (switch_connected_state_set), self);
Packit Service fc05fa
Packit Service fc05fa
	/* Styling */
Packit Service fc05fa
	gtk_image_set_pixel_size (GTK_IMAGE (WID ("image")), ICON_SIZE);
Packit Service fc05fa
Packit Service fc05fa
	context = gtk_widget_get_style_context (WID ("delete_button"));
Packit Service fc05fa
	gtk_style_context_add_class (context, "destructive-action");
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
setup_pairing_agent (BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
Packit Service fc05fa
	priv->agent = bluetooth_agent_new (AGENT_PATH);
Packit Service fc05fa
	if (bluetooth_agent_register (priv->agent) == FALSE) {
Packit Service fc05fa
		g_clear_object (&priv->agent);
Packit Service fc05fa
		return;
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	bluetooth_agent_set_pincode_func (priv->agent, pincode_callback, self);
Packit Service fc05fa
	bluetooth_agent_set_passkey_func (priv->agent, passkey_callback, self);
Packit Service fc05fa
	bluetooth_agent_set_display_func (priv->agent, display_callback, self);
Packit Service fc05fa
	bluetooth_agent_set_display_pincode_func (priv->agent, display_pincode_callback, self);
Packit Service fc05fa
	bluetooth_agent_set_cancel_func (priv->agent, cancel_callback, self);
Packit Service fc05fa
	bluetooth_agent_set_confirm_func (priv->agent, confirm_callback, self);
Packit Service fc05fa
	bluetooth_agent_set_authorize_func (priv->agent, authorize_callback, self);
Packit Service fc05fa
	bluetooth_agent_set_authorize_service_func (priv->agent, authorize_service_callback, self);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
session_properties_changed_cb (GDBusProxy               *session,
Packit Service fc05fa
			       GVariant                 *changed,
Packit Service fc05fa
			       char                    **invalidated,
Packit Service fc05fa
			       BluetoothSettingsWidget  *self)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	GVariant *v;
Packit Service fc05fa
Packit Service fc05fa
	v = g_variant_lookup_value (changed, "SessionIsActive", G_VARIANT_TYPE_BOOLEAN);
Packit Service fc05fa
	if (v) {
Packit Service fc05fa
		priv->has_console = g_variant_get_boolean (v);
Packit Service fc05fa
		g_debug ("Received session is active change: now %s", priv->has_console ? "active" : "inactive");
Packit Service fc05fa
		g_variant_unref (v);
Packit Service fc05fa
Packit Service fc05fa
		if (priv->has_console)
Packit Service fc05fa
			obex_agent_up ();
Packit Service fc05fa
		else
Packit Service fc05fa
			obex_agent_down ();
Packit Service fc05fa
	}
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static gboolean
Packit Service fc05fa
is_session_active (BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	GVariant *variant;
Packit Service fc05fa
	gboolean is_session_active = FALSE;
Packit Service fc05fa
Packit Service fc05fa
	variant = g_dbus_proxy_get_cached_property (priv->session_proxy,
Packit Service fc05fa
						    "SessionIsActive");
Packit Service fc05fa
	if (variant) {
Packit Service fc05fa
		is_session_active = g_variant_get_boolean (variant);
Packit Service fc05fa
		g_variant_unref (variant);
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	return is_session_active;
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
setup_obex (BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	GError *error = NULL;
Packit Service fc05fa
Packit Service fc05fa
	priv->session_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
Packit Service fc05fa
							     G_DBUS_PROXY_FLAGS_NONE,
Packit Service fc05fa
							     NULL,
Packit Service fc05fa
							     GNOME_SESSION_DBUS_NAME,
Packit Service fc05fa
							     GNOME_SESSION_DBUS_OBJECT,
Packit Service fc05fa
							     GNOME_SESSION_DBUS_INTERFACE,
Packit Service fc05fa
							     NULL,
Packit Service fc05fa
							     &error);
Packit Service fc05fa
Packit Service fc05fa
	if (priv->session_proxy == NULL) {
Packit Service fc05fa
		g_warning ("Failed to get session proxy: %s", error->message);
Packit Service fc05fa
		g_error_free (error);
Packit Service fc05fa
		return;
Packit Service fc05fa
	}
Packit Service fc05fa
	g_signal_connect (priv->session_proxy, "g-properties-changed",
Packit Service fc05fa
			  G_CALLBACK (session_properties_changed_cb), self);
Packit Service fc05fa
	priv->has_console = is_session_active (self);
Packit Service fc05fa
Packit Service fc05fa
	if (priv->has_console)
Packit Service fc05fa
		obex_agent_up ();
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
bluetooth_settings_widget_init (BluetoothSettingsWidget *self)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (self);
Packit Service fc05fa
	GtkWidget *widget;
Packit Service fc05fa
	GError *error = NULL;
Packit Service fc05fa
Packit Service fc05fa
	/* This ensures the BluetoothHdyColumn type is known by GtkBuilder when
Packit Service fc05fa
	 * loading the UI template.
Packit Service fc05fa
	 */
Packit Service fc05fa
	g_type_ensure (BLUETOOTH_TYPE_HDY_COLUMN);
Packit Service fc05fa
Packit Service fc05fa
	priv->cancellable = g_cancellable_new ();
Packit Service fc05fa
	priv->debug = g_getenv ("BLUETOOTH_DEBUG") != NULL;
Packit Service fc05fa
Packit Service fc05fa
	g_resources_register (bluetooth_settings_get_resource ());
Packit Service fc05fa
	priv->builder = gtk_builder_new ();
Packit Service fc05fa
	gtk_builder_set_translation_domain (priv->builder, GETTEXT_PACKAGE);
Packit Service fc05fa
	gtk_builder_add_from_resource (priv->builder,
Packit Service fc05fa
                                       "/org/gnome/bluetooth/settings.ui",
Packit Service fc05fa
                                       &error);
Packit Service fc05fa
	if (error != NULL) {
Packit Service fc05fa
		g_warning ("Could not load ui: %s", error->message);
Packit Service fc05fa
		g_error_free (error);
Packit Service fc05fa
		return;
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	widget = WID ("scrolledwindow1");
Packit Service fc05fa
Packit Service fc05fa
	priv->connecting_devices = g_hash_table_new_full (g_str_hash,
Packit Service fc05fa
								g_str_equal,
Packit Service fc05fa
								(GDestroyNotify) g_free,
Packit Service fc05fa
								NULL);
Packit Service fc05fa
	priv->pairing_devices = g_hash_table_new_full (g_str_hash,
Packit Service fc05fa
						       g_str_equal,
Packit Service fc05fa
						       (GDestroyNotify) g_free,
Packit Service fc05fa
						       NULL);
Packit Service fc05fa
	priv->devices_type = g_hash_table_new_full (g_str_hash,
Packit Service fc05fa
						    g_str_equal,
Packit Service fc05fa
						    (GDestroyNotify) g_free,
Packit Service fc05fa
						    NULL);
Packit Service fc05fa
Packit Service fc05fa
	setup_pairing_agent (self);
Packit Service fc05fa
	priv->client = bluetooth_client_new ();
Packit Service fc05fa
	g_signal_connect (G_OBJECT (priv->client), "notify::default-adapter-name",
Packit Service fc05fa
			  G_CALLBACK (name_changed), self);
Packit Service fc05fa
	priv->model = bluetooth_client_get_model (priv->client);
Packit Service fc05fa
	g_signal_connect (priv->model, "row-changed",
Packit Service fc05fa
			  G_CALLBACK (row_changed_cb), self);
Packit Service fc05fa
	g_signal_connect (priv->model, "row-inserted",
Packit Service fc05fa
			  G_CALLBACK (row_inserted_cb), self);
Packit Service fc05fa
	g_signal_connect (priv->client, "device-removed",
Packit Service fc05fa
			  G_CALLBACK (device_removed_cb), self);
Packit Service fc05fa
	g_signal_connect (G_OBJECT (priv->client), "notify::default-adapter",
Packit Service fc05fa
			  G_CALLBACK (default_adapter_changed), self);
Packit Service fc05fa
	g_signal_connect (G_OBJECT (priv->client), "notify::default-adapter-powered",
Packit Service fc05fa
			  G_CALLBACK (default_adapter_changed), self);
Packit Service fc05fa
	default_adapter_changed (priv->client, NULL, self);
Packit Service fc05fa
Packit Service fc05fa
	priv->row_sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
Packit Service fc05fa
Packit Service fc05fa
	add_device_section (self);
Packit Service fc05fa
Packit Service fc05fa
	gtk_widget_set_hexpand (widget, TRUE);
Packit Service fc05fa
	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (widget),
Packit Service fc05fa
					GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
Packit Service fc05fa
	gtk_container_add (GTK_CONTAINER (self), widget);
Packit Service fc05fa
Packit Service fc05fa
	setup_properties_dialog (self);
Packit Service fc05fa
Packit Service fc05fa
	gtk_widget_show_all (GTK_WIDGET (self));
Packit Service fc05fa
Packit Service fc05fa
	setup_obex (self);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
bluetooth_settings_widget_finalize (GObject *object)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidget *widget = BLUETOOTH_SETTINGS_WIDGET(object);
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (widget);
Packit Service fc05fa
Packit Service fc05fa
	g_clear_object (&priv->agent);
Packit Service fc05fa
	g_clear_pointer (&priv->properties_dialog, gtk_widget_destroy);
Packit Service fc05fa
	g_clear_pointer (&priv->pairing_dialog, gtk_widget_destroy);
Packit Service fc05fa
	g_clear_object (&priv->session_proxy);
Packit Service fc05fa
Packit Service fc05fa
	obex_agent_down ();
Packit Service fc05fa
Packit Service fc05fa
	/* See default_adapter_changed () */
Packit Service fc05fa
	/* FIXME: This is blocking */
Packit Service fc05fa
	if (priv->client) {
Packit Service fc05fa
		g_object_set (G_OBJECT (priv->client), "default-adapter-discovering", FALSE, NULL);
Packit Service fc05fa
		g_object_set (G_OBJECT (priv->client), "default-adapter-discoverable", FALSE, NULL);
Packit Service fc05fa
	}
Packit Service fc05fa
Packit Service fc05fa
	g_cancellable_cancel (priv->cancellable);
Packit Service fc05fa
	g_clear_object (&priv->cancellable);
Packit Service fc05fa
Packit Service fc05fa
	g_clear_object (&priv->model);
Packit Service fc05fa
	g_clear_object (&priv->client);
Packit Service fc05fa
	g_clear_object (&priv->builder);
Packit Service fc05fa
Packit Service fc05fa
	g_clear_pointer (&priv->devices_type, g_hash_table_destroy);
Packit Service fc05fa
	g_clear_pointer (&priv->connecting_devices, g_hash_table_destroy);
Packit Service fc05fa
	g_clear_pointer (&priv->pairing_devices, g_hash_table_destroy);
Packit Service fc05fa
	g_clear_pointer (&priv->selected_name, g_free);
Packit Service fc05fa
	g_clear_pointer (&priv->selected_object_path, g_free);
Packit Service fc05fa
Packit Service fc05fa
	G_OBJECT_CLASS(bluetooth_settings_widget_parent_class)->finalize(object);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
static void
Packit Service fc05fa
bluetooth_settings_widget_class_init (BluetoothSettingsWidgetClass *klass)
Packit Service fc05fa
{
Packit Service fc05fa
	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
Packit Service fc05fa
	bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
Packit Service fc05fa
Packit Service fc05fa
	G_OBJECT_CLASS (klass)->finalize = bluetooth_settings_widget_finalize;
Packit Service fc05fa
Packit Service fc05fa
	/**
Packit Service fc05fa
	 * BluetoothSettingsWidget::panel-changed:
Packit Service fc05fa
	 * @chooser: a #BluetoothSettingsWidget widget which received the signal
Packit Service fc05fa
	 * @panel: the new panel that the Settings application should now open
Packit Service fc05fa
	 *
Packit Service fc05fa
	 * The #BluetoothChooser::panel-changed signal is launched when a
Packit Service fc05fa
	 * link to another settings panel is clicked.
Packit Service fc05fa
	 **/
Packit Service fc05fa
	signals[PANEL_CHANGED] =
Packit Service fc05fa
		g_signal_new ("panel-changed",
Packit Service fc05fa
			      G_TYPE_FROM_CLASS (klass),
Packit Service fc05fa
			      G_SIGNAL_RUN_LAST,
Packit Service fc05fa
			      0,
Packit Service fc05fa
			      NULL, NULL,
Packit Service fc05fa
			      g_cclosure_marshal_VOID__STRING,
Packit Service fc05fa
			      G_TYPE_NONE, 1, G_TYPE_STRING);
Packit Service fc05fa
Packit Service fc05fa
	/**
Packit Service fc05fa
	 * BluetoothSettingsWidget::adapter-status-changed:
Packit Service fc05fa
	 * @chooser: a #BluetoothSettingsWidget widget which received the signal
Packit Service fc05fa
	 *
Packit Service fc05fa
	 * The #BluetoothChooser::adapter-status-changed signal is launched when the status
Packit Service fc05fa
	 * of the adapter changes (powered, available, etc.).
Packit Service fc05fa
	 **/
Packit Service fc05fa
	signals[ADAPTER_STATUS_CHANGED] =
Packit Service fc05fa
		g_signal_new ("adapter-status-changed",
Packit Service fc05fa
			      G_TYPE_FROM_CLASS (klass),
Packit Service fc05fa
			      G_SIGNAL_RUN_LAST,
Packit Service fc05fa
			      0,
Packit Service fc05fa
			      NULL, NULL,
Packit Service fc05fa
			      g_cclosure_marshal_VOID__VOID,
Packit Service fc05fa
			      G_TYPE_NONE, 0, G_TYPE_NONE);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
/**
Packit Service fc05fa
 * bluetooth_settings_widget_new:
Packit Service fc05fa
 *
Packit Service fc05fa
 * Returns a new #BluetoothSettingsWidget widget.
Packit Service fc05fa
 *
Packit Service fc05fa
 * Return value: A #BluetoothSettingsWidget widget
Packit Service fc05fa
 **/
Packit Service fc05fa
GtkWidget *
Packit Service fc05fa
bluetooth_settings_widget_new (void)
Packit Service fc05fa
{
Packit Service fc05fa
	return g_object_new (BLUETOOTH_TYPE_SETTINGS_WIDGET, NULL);
Packit Service fc05fa
}
Packit Service fc05fa
Packit Service fc05fa
/**
Packit Service fc05fa
 * bluetooth_settings_widget_get_default_adapter_powered:
Packit Service fc05fa
 * @widget: a #BluetoothSettingsWidget widget.
Packit Service fc05fa
 *
Packit Service fc05fa
 * Return value: Whether the default Bluetooth adapter is powered.
Packit Service fc05fa
 **/
Packit Service fc05fa
gboolean
Packit Service fc05fa
bluetooth_settings_widget_get_default_adapter_powered (BluetoothSettingsWidget *widget)
Packit Service fc05fa
{
Packit Service fc05fa
	BluetoothSettingsWidgetPrivate *priv;
Packit Service fc05fa
	gboolean ret;
Packit Service fc05fa
Packit Service fc05fa
	g_return_val_if_fail (BLUETOOTH_IS_SETTINGS_WIDGET (widget), FALSE);
Packit Service fc05fa
Packit Service fc05fa
	priv = BLUETOOTH_SETTINGS_WIDGET_GET_PRIVATE (widget);
Packit Service fc05fa
	g_object_get (G_OBJECT (priv->client),
Packit Service fc05fa
		      "default-adapter-powered", &ret,
Packit Service fc05fa
		      NULL);
Packit Service fc05fa
Packit Service fc05fa
	return ret;
Packit Service fc05fa
}