Blame src/applet.c

Packit Service 639700
// SPDX-License-Identifier: GPL-2.0+
Packit fabffb
/* NetworkManager Applet -- allow user control over networking
Packit fabffb
 *
Packit fabffb
 * Copyright (C) 2004 - 2017 Red Hat, Inc.
Packit fabffb
 * Copyright (C) 2005 - 2008 Novell, Inc.
Packit fabffb
 *
Packit fabffb
 * This applet used the GNOME Wireless Applet as a skeleton to build from.
Packit fabffb
 *
Packit fabffb
 * GNOME Wireless Applet Authors:
Packit fabffb
 *		Eskil Heyn Olsen <eskil@eskil.dk>
Packit fabffb
 *		Bastien Nocera <hadess@hadess.net> (Gnome2 port)
Packit fabffb
 *
Packit fabffb
 * Copyright 2001, 2002 Free Software Foundation
Packit fabffb
 */
Packit fabffb
Packit fabffb
#include "nm-default.h"
Packit fabffb
Packit fabffb
#include <time.h>
Packit fabffb
#include <string.h>
Packit fabffb
#include <strings.h>
Packit fabffb
#include <unistd.h>
Packit fabffb
#include <sys/socket.h>
Packit fabffb
#include <stdlib.h>
Packit fabffb
#include <libnotify/notify.h>
Packit fabffb
Packit fabffb
#include "applet.h"
Packit fabffb
#include "applet-device-bt.h"
Packit fabffb
#include "applet-device-ethernet.h"
Packit fabffb
#include "applet-device-wifi.h"
Packit fabffb
#include "applet-dialogs.h"
Packit fabffb
#include "nma-wifi-dialog.h"
Packit fabffb
#include "applet-vpn-request.h"
Packit fabffb
#include "utils.h"
Packit fabffb
Packit fabffb
#if WITH_WWAN
Packit fabffb
# include "applet-device-broadband.h"
Packit fabffb
#endif
Packit fabffb
Packit fabffb
#define NOTIFY_CAPS_ACTIONS_KEY "actions"
Packit fabffb
Packit fabffb
extern gboolean shell_debug;
Packit fabffb
extern gboolean with_agent;
Packit fabffb
extern gboolean with_appindicator;
Packit fabffb
Packit fabffb
G_DEFINE_TYPE (NMApplet, nma, G_TYPE_APPLICATION)
Packit fabffb
Packit fabffb
/********************************************************************/
Packit fabffb
Packit fabffb
static gboolean
Packit fabffb
applet_request_wifi_scan (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	const GPtrArray *devices;
Packit fabffb
	NMDevice *device;
Packit fabffb
	int i;
Packit fabffb
Packit fabffb
	g_debug ("requesting wifi scan");
Packit fabffb
Packit fabffb
	/* Request scan for all wifi devices */
Packit fabffb
	devices = nm_client_get_devices (applet->nm_client);
Packit fabffb
	for (i = 0; devices && i < devices->len; i++) {
Packit fabffb
		device = g_ptr_array_index (devices, i);
Packit fabffb
		if (NM_IS_DEVICE_WIFI (device))
Packit fabffb
			nm_device_wifi_request_scan ((NMDeviceWifi *) device, NULL, NULL);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	return G_SOURCE_CONTINUE;
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_start_wifi_scan (NMApplet *applet, gpointer unused)
Packit fabffb
{
Packit fabffb
	nm_clear_g_source (&applet->wifi_scan_id);
Packit fabffb
	applet->wifi_scan_id = g_timeout_add_seconds (15,
Packit fabffb
	                                              (GSourceFunc) applet_request_wifi_scan,
Packit fabffb
	                                              applet);
Packit fabffb
	applet_request_wifi_scan (applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_stop_wifi_scan (NMApplet *applet, gpointer unused)
Packit fabffb
{
Packit fabffb
	nm_clear_g_source (&applet->wifi_scan_id);
Packit fabffb
}
Packit fabffb
Packit fabffb
static inline NMADeviceClass *
Packit fabffb
get_device_class (NMDevice *device, NMApplet *applet)
Packit fabffb
{
Packit fabffb
	g_return_val_if_fail (device != NULL, NULL);
Packit fabffb
	g_return_val_if_fail (applet != NULL, NULL);
Packit fabffb
Packit fabffb
	if (NM_IS_DEVICE_ETHERNET (device))
Packit fabffb
		return applet->ethernet_class;
Packit fabffb
	else if (NM_IS_DEVICE_WIFI (device))
Packit fabffb
		return applet->wifi_class;
Packit fabffb
	else if (NM_IS_DEVICE_MODEM (device)) {
Packit fabffb
#if WITH_WWAN
Packit fabffb
		return applet->broadband_class;
Packit fabffb
#else
Packit fabffb
		g_debug ("%s: modem found but WWAN support not enabled", __func__);
Packit fabffb
#endif
Packit fabffb
	} else if (NM_IS_DEVICE_BT (device))
Packit fabffb
		return applet->bt_class;
Packit fabffb
	else
Packit fabffb
		g_debug ("%s: Unknown device type '%s'", __func__, G_OBJECT_TYPE_NAME (device));
Packit fabffb
	return NULL;
Packit fabffb
}
Packit fabffb
Packit fabffb
static inline NMADeviceClass *
Packit fabffb
get_device_class_from_connection (NMConnection *connection, NMApplet *applet)
Packit fabffb
{
Packit fabffb
	NMSettingConnection *s_con;
Packit fabffb
	const char *ctype;
Packit fabffb
Packit fabffb
	g_return_val_if_fail (connection != NULL, NULL);
Packit fabffb
	g_return_val_if_fail (applet != NULL, NULL);
Packit fabffb
Packit fabffb
	s_con = nm_connection_get_setting_connection (connection);
Packit fabffb
	g_return_val_if_fail (s_con != NULL, NULL);
Packit fabffb
Packit fabffb
	ctype = nm_setting_connection_get_connection_type (s_con);
Packit fabffb
	g_return_val_if_fail (ctype != NULL, NULL);
Packit fabffb
Packit fabffb
	if (!strcmp (ctype, NM_SETTING_WIRED_SETTING_NAME) || !strcmp (ctype, NM_SETTING_PPPOE_SETTING_NAME))
Packit fabffb
		return applet->ethernet_class;
Packit fabffb
	else if (!strcmp (ctype, NM_SETTING_WIRELESS_SETTING_NAME))
Packit fabffb
		return applet->wifi_class;
Packit fabffb
#if WITH_WWAN
Packit fabffb
	else if (!strcmp (ctype, NM_SETTING_GSM_SETTING_NAME) || !strcmp (ctype, NM_SETTING_CDMA_SETTING_NAME))
Packit fabffb
		return applet->broadband_class;
Packit fabffb
#endif
Packit fabffb
	else if (!strcmp (ctype, NM_SETTING_BLUETOOTH_SETTING_NAME))
Packit fabffb
		return applet->bt_class;
Packit fabffb
	else
Packit fabffb
		g_warning ("%s: unhandled connection type '%s'", __func__, ctype);
Packit fabffb
	return NULL;
Packit fabffb
}
Packit fabffb
Packit fabffb
static NMActiveConnection *
Packit fabffb
applet_get_best_activating_connection (NMApplet *applet, NMDevice **device)
Packit fabffb
{
Packit fabffb
	NMActiveConnection *best = NULL;
Packit fabffb
	NMDevice *best_dev = NULL;
Packit fabffb
	const GPtrArray *connections;
Packit fabffb
	int i;
Packit fabffb
Packit fabffb
	g_return_val_if_fail (NM_IS_APPLET (applet), NULL);
Packit fabffb
	g_return_val_if_fail (device != NULL, NULL);
Packit fabffb
	g_return_val_if_fail (*device == NULL, NULL);
Packit fabffb
Packit fabffb
	connections = nm_client_get_active_connections (applet->nm_client);
Packit fabffb
	for (i = 0; connections && (i < connections->len); i++) {
Packit fabffb
		NMActiveConnection *candidate = g_ptr_array_index (connections, i);
Packit fabffb
		const GPtrArray *devices;
Packit fabffb
		NMDevice *candidate_dev;
Packit fabffb
Packit fabffb
		if (nm_active_connection_get_state (candidate) != NM_ACTIVE_CONNECTION_STATE_ACTIVATING)
Packit fabffb
			continue;
Packit fabffb
Packit fabffb
		devices = nm_active_connection_get_devices (candidate);
Packit fabffb
		if (!devices || !devices->len)
Packit fabffb
			continue;
Packit fabffb
Packit fabffb
		candidate_dev = g_ptr_array_index (devices, 0);
Packit fabffb
		if (!get_device_class (candidate_dev, applet))
Packit fabffb
			continue;
Packit fabffb
Packit fabffb
		if (!best_dev) {
Packit fabffb
			best_dev = candidate_dev;
Packit fabffb
			best = candidate;
Packit fabffb
			continue;
Packit fabffb
		}
Packit fabffb
Packit fabffb
		if (NM_IS_DEVICE_WIFI (best_dev)) {
Packit fabffb
			if (NM_IS_DEVICE_ETHERNET (candidate_dev)) {
Packit fabffb
				best_dev = candidate_dev;
Packit fabffb
				best = candidate;
Packit fabffb
			}
Packit fabffb
		} else if (NM_IS_DEVICE_MODEM (best_dev)) {
Packit fabffb
			NMDeviceModemCapabilities best_caps;
Packit fabffb
			NMDeviceModemCapabilities candidate_caps = NM_DEVICE_MODEM_CAPABILITY_NONE;
Packit fabffb
Packit fabffb
			best_caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (best_dev));
Packit fabffb
			if (NM_IS_DEVICE_MODEM (candidate_dev))
Packit fabffb
				candidate_caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (candidate_dev));
Packit fabffb
Packit fabffb
			if (best_caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) {
Packit fabffb
				if (   NM_IS_DEVICE_ETHERNET (candidate_dev)
Packit fabffb
				    || NM_IS_DEVICE_WIFI (candidate_dev)) {
Packit fabffb
					best_dev = candidate_dev;
Packit fabffb
					best = candidate;
Packit fabffb
				}
Packit fabffb
			} else if (best_caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS) {
Packit fabffb
				if (   NM_IS_DEVICE_ETHERNET (candidate_dev)
Packit fabffb
					|| NM_IS_DEVICE_WIFI (candidate_dev)
Packit fabffb
					|| (candidate_caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO)) {
Packit fabffb
					best_dev = candidate_dev;
Packit fabffb
					best = candidate;
Packit fabffb
				}
Packit fabffb
			}
Packit fabffb
		}
Packit fabffb
	}
Packit fabffb
Packit fabffb
	*device = best_dev;
Packit fabffb
	return best;
Packit fabffb
}
Packit fabffb
Packit fabffb
static NMActiveConnection *
Packit fabffb
applet_get_default_active_connection (NMApplet *applet, NMDevice **device,
Packit fabffb
                                      gboolean only_known_devices)
Packit fabffb
{
Packit fabffb
	NMActiveConnection *default_ac = NULL;
Packit fabffb
	NMDevice *non_default_device = NULL;
Packit fabffb
	NMActiveConnection *non_default_ac = NULL;
Packit fabffb
	const GPtrArray *connections;
Packit fabffb
	int i;
Packit fabffb
Packit fabffb
	g_return_val_if_fail (NM_IS_APPLET (applet), NULL);
Packit fabffb
	g_return_val_if_fail (device != NULL, NULL);
Packit fabffb
	g_return_val_if_fail (*device == NULL, NULL);
Packit fabffb
Packit fabffb
	connections = nm_client_get_active_connections (applet->nm_client);
Packit fabffb
	for (i = 0; connections && (i < connections->len); i++) {
Packit fabffb
		NMActiveConnection *candidate = g_ptr_array_index (connections, i);
Packit fabffb
		NMDevice *candidate_dev;
Packit fabffb
		const GPtrArray *devices;
Packit fabffb
Packit fabffb
		devices = nm_active_connection_get_devices (candidate);
Packit fabffb
		if (!devices || !devices->len)
Packit fabffb
			continue;
Packit fabffb
Packit fabffb
		candidate_dev = g_ptr_array_index (devices, 0);
Packit fabffb
Packit fabffb
		if (   only_known_devices
Packit fabffb
		    && !get_device_class (candidate_dev, applet))
Packit fabffb
			continue;
Packit fabffb
Packit fabffb
		/* We have to return default connection/device even if they are of an
Packit fabffb
		 * unknown class - otherwise we may end up returning non
Packit fabffb
		 * default interface which has nothing to do with our default
Packit fabffb
		 * route, e.g. we may return slave ethernet when we have
Packit fabffb
		 * defult route going through bond */
Packit fabffb
Packit fabffb
		if (nm_active_connection_get_default (candidate)) {
Packit fabffb
			if (!default_ac) {
Packit fabffb
				*device = candidate_dev;
Packit fabffb
				default_ac = candidate;
Packit fabffb
			}
Packit fabffb
		} else {
Packit fabffb
			if (!non_default_ac) {
Packit fabffb
				non_default_device = candidate_dev;
Packit fabffb
				non_default_ac = candidate;
Packit fabffb
			}
Packit fabffb
		}
Packit fabffb
	}
Packit fabffb
Packit fabffb
	/* Prefer the default connection if one exists, otherwise return the first
Packit fabffb
	 * non-default connection.
Packit fabffb
	 */
Packit fabffb
	if (!default_ac && non_default_ac) {
Packit fabffb
		default_ac = non_default_ac;
Packit fabffb
		*device = non_default_device;
Packit fabffb
	}
Packit fabffb
	return default_ac;
Packit fabffb
}
Packit fabffb
Packit fabffb
GPtrArray *
Packit fabffb
applet_get_all_connections (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	const GPtrArray *all_connections;
Packit fabffb
	GPtrArray *connections;
Packit fabffb
	int i;
Packit fabffb
	NMConnection *connection;
Packit fabffb
	NMSettingConnection *s_con;
Packit fabffb
Packit fabffb
	all_connections = nm_client_get_connections (applet->nm_client);
Packit fabffb
	connections = g_ptr_array_new_full (all_connections->len, g_object_unref);
Packit fabffb
Packit fabffb
	/* Ignore slave connections unless they are wifi connections */
Packit fabffb
	for (i = 0; i < all_connections->len; i++) {
Packit fabffb
		connection = all_connections->pdata[i];
Packit fabffb
Packit fabffb
		s_con = nm_connection_get_setting_connection (connection);
Packit fabffb
		if (   s_con
Packit fabffb
		    && (   !nm_setting_connection_get_master (s_con)
Packit fabffb
		        || nm_connection_get_setting_wireless (connection)))
Packit fabffb
			g_ptr_array_add (connections, g_object_ref (connection));
Packit fabffb
	}
Packit fabffb
Packit fabffb
	return connections;
Packit fabffb
}
Packit fabffb
Packit fabffb
static NMActiveConnection *
Packit fabffb
applet_get_active_for_connection (NMApplet *applet, NMConnection *connection)
Packit fabffb
{
Packit fabffb
	const GPtrArray *active_list;
Packit fabffb
	int i;
Packit fabffb
	const char *cpath;
Packit fabffb
Packit fabffb
	cpath = nm_connection_get_path (connection);
Packit fabffb
	g_return_val_if_fail (cpath != NULL, NULL);
Packit fabffb
Packit fabffb
	active_list = nm_client_get_active_connections (applet->nm_client);
Packit fabffb
	for (i = 0; active_list && (i < active_list->len); i++) {
Packit fabffb
		NMActiveConnection *active = NM_ACTIVE_CONNECTION (g_ptr_array_index (active_list, i));
Packit fabffb
		NMRemoteConnection *conn = nm_active_connection_get_connection (active);
Packit fabffb
Packit fabffb
		if (conn) {
Packit fabffb
			const char *active_cpath = nm_connection_get_path (NM_CONNECTION (conn));
Packit fabffb
Packit fabffb
			if (active_cpath && !strcmp (active_cpath, cpath))
Packit fabffb
				return active;
Packit fabffb
		}
Packit fabffb
	}
Packit fabffb
	return NULL;
Packit fabffb
}
Packit fabffb
Packit fabffb
NMDevice *
Packit fabffb
applet_get_device_for_connection (NMApplet *applet, NMConnection *connection)
Packit fabffb
{
Packit fabffb
	const GPtrArray *active_list;
Packit fabffb
	const char *cpath;
Packit fabffb
	int i;
Packit fabffb
Packit fabffb
	cpath = nm_connection_get_path (connection);
Packit fabffb
	g_return_val_if_fail (cpath != NULL, NULL);
Packit fabffb
Packit fabffb
	active_list = nm_client_get_active_connections (applet->nm_client);
Packit fabffb
	for (i = 0; active_list && (i < active_list->len); i++) {
Packit fabffb
		NMActiveConnection *active = NM_ACTIVE_CONNECTION (g_ptr_array_index (active_list, i));
Packit fabffb
		NMRemoteConnection *ac_conn = nm_active_connection_get_connection (active);
Packit fabffb
Packit fabffb
		if (!g_strcmp0 (nm_connection_get_path (NM_CONNECTION (ac_conn)), cpath))
Packit fabffb
			return g_ptr_array_index (nm_active_connection_get_devices (active), 0);
Packit fabffb
	}
Packit fabffb
	return NULL;
Packit fabffb
}
Packit fabffb
Packit fabffb
typedef struct {
Packit fabffb
	NMApplet *applet;
Packit fabffb
	NMDevice *device;
Packit fabffb
	char *specific_object;
Packit fabffb
	NMConnection *connection;
Packit fabffb
} AppletItemActivateInfo;
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_item_activate_info_destroy (AppletItemActivateInfo *info)
Packit fabffb
{
Packit fabffb
	g_return_if_fail (info != NULL);
Packit fabffb
Packit fabffb
	if (info->device)
Packit fabffb
		g_object_unref (info->device);
Packit fabffb
	g_free (info->specific_object);
Packit fabffb
	if (info->connection)
Packit fabffb
		g_object_unref (info->connection);
Packit fabffb
	memset (info, 0, sizeof (AppletItemActivateInfo));
Packit fabffb
	g_free (info);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
add_and_activate_cb (GObject *client,
Packit fabffb
                     GAsyncResult *result,
Packit fabffb
                     gpointer user_data)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (user_data);
Packit fabffb
	GError *error = NULL;
Packit fabffb
	NMActiveConnection *active;
Packit fabffb
Packit fabffb
	active = nm_client_add_and_activate_connection_finish (NM_CLIENT (client), result, &error);
Packit fabffb
	g_clear_object (&active);
Packit fabffb
Packit fabffb
	if (error) {
Packit fabffb
		const char *text = _("Failed to add/activate connection");
Packit fabffb
		char *err_text = g_strdup_printf ("(%d) %s", error->code,
Packit fabffb
		                                  error->message ? error->message : _("Unknown error"));
Packit fabffb
Packit fabffb
		g_warning ("%s: %s", text, err_text);
Packit fabffb
		utils_show_error_dialog (_("Connection failure"), text, err_text, FALSE, NULL);
Packit fabffb
		g_free (err_text);
Packit fabffb
		g_error_free (error);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	applet_schedule_update_icon (applet);
Packit fabffb
	applet_schedule_update_menu (applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_menu_item_activate_helper_new_connection (NMConnection *connection,
Packit fabffb
                                                 gboolean auto_created,
Packit fabffb
                                                 gboolean canceled,
Packit fabffb
                                                 gpointer user_data)
Packit fabffb
{
Packit fabffb
	AppletItemActivateInfo *info = user_data;
Packit fabffb
Packit fabffb
	if (canceled) {
Packit fabffb
		applet_item_activate_info_destroy (info);
Packit fabffb
		return;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	g_return_if_fail (connection != NULL);
Packit fabffb
Packit fabffb
	/* Ask NM to add the new connection and activate it; NM will fill in the
Packit fabffb
	 * missing details based on the specific object and the device.
Packit fabffb
	 */
Packit fabffb
	nm_client_add_and_activate_connection_async (info->applet->nm_client,
Packit fabffb
	                                             connection,
Packit fabffb
	                                             info->device,
Packit fabffb
	                                             info->specific_object,
Packit fabffb
	                                             NULL,
Packit fabffb
	                                             add_and_activate_cb,
Packit fabffb
	                                             info->applet);
Packit fabffb
Packit fabffb
	applet_item_activate_info_destroy (info);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
disconnect_cb (GObject *device,
Packit fabffb
               GAsyncResult *result,
Packit fabffb
               gpointer user_data)
Packit fabffb
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (user_data);
Packit fabffb
	GError *error = NULL;
Packit fabffb
Packit fabffb
	nm_device_disconnect_finish (NM_DEVICE (device), result, &error);
Packit fabffb
	if (error) {
Packit fabffb
		const char *text = _("Device disconnect failed");
Packit fabffb
		char *err_text = g_strdup_printf ("(%d) %s", error->code,
Packit fabffb
		                                  error->message ? error->message : _("Unknown error"));
Packit fabffb
Packit fabffb
		g_warning ("%s: %s: %s", __func__, text, err_text);
Packit fabffb
		utils_show_error_dialog (_("Disconnect failure"), text, err_text, FALSE, NULL);
Packit fabffb
		g_free (err_text);
Packit fabffb
		g_error_free (error);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	applet_schedule_update_icon (applet);
Packit fabffb
	applet_schedule_update_menu (applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
void
Packit fabffb
applet_menu_item_disconnect_helper (NMDevice *device,
Packit fabffb
                                    NMApplet *applet)
Packit fabffb
{
Packit fabffb
	g_return_if_fail (NM_IS_DEVICE (device));
Packit fabffb
Packit fabffb
	nm_device_disconnect_async (device, NULL, disconnect_cb, applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
activate_connection_cb (GObject *client,
Packit fabffb
                        GAsyncResult *result,
Packit fabffb
                        gpointer user_data)
Packit fabffb
{
Packit fabffb
	GError *error = NULL;
Packit fabffb
	NMActiveConnection *active;
Packit fabffb
Packit fabffb
	active = nm_client_activate_connection_finish (NM_CLIENT (client), result, &error);
Packit fabffb
	g_clear_object (&active);
Packit fabffb
Packit fabffb
	if (error) {
Packit fabffb
		const char *text = _("Connection activation failed");
Packit fabffb
		char *err_text = g_strdup_printf ("(%d) %s", error->code,
Packit fabffb
		                                  error->message ? error->message : _("Unknown error"));
Packit fabffb
Packit fabffb
		g_warning ("%s: %s", text, err_text);
Packit fabffb
		utils_show_error_dialog (_("Connection failure"), text, err_text, FALSE, NULL);
Packit fabffb
		g_free (err_text);
Packit fabffb
		g_error_free (error);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	applet_schedule_update_icon (NM_APPLET (user_data));
Packit fabffb
}
Packit fabffb
Packit fabffb
void
Packit fabffb
applet_menu_item_activate_helper (NMDevice *device,
Packit fabffb
                                  NMConnection *connection,
Packit fabffb
                                  const char *specific_object,
Packit fabffb
                                  NMApplet *applet,
Packit fabffb
                                  gpointer dclass_data)
Packit fabffb
{
Packit fabffb
	AppletItemActivateInfo *info;
Packit fabffb
	NMADeviceClass *dclass;
Packit fabffb
Packit fabffb
	if (connection) {
Packit fabffb
		/* If the menu item had an associated connection already, just tell
Packit fabffb
		 * NM to activate that connection.
Packit fabffb
		 */
Packit fabffb
		nm_client_activate_connection_async (applet->nm_client,
Packit fabffb
		                                     connection,
Packit fabffb
		                                     device,
Packit fabffb
		                                     specific_object,
Packit fabffb
		                                     NULL,
Packit fabffb
		                                     activate_connection_cb,
Packit fabffb
		                                     applet);
Packit fabffb
		return;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	g_return_if_fail (NM_IS_DEVICE (device));
Packit fabffb
Packit fabffb
	/* If no connection was given, ask the device class to create a new
Packit fabffb
	 * default connection for this device type.  This could be a wizard,
Packit fabffb
	 * and thus take a while.
Packit fabffb
	 */
Packit fabffb
Packit fabffb
	info = g_malloc0 (sizeof (AppletItemActivateInfo));
Packit fabffb
	info->applet = applet;
Packit fabffb
	info->specific_object = g_strdup (specific_object);
Packit fabffb
	info->device = g_object_ref (device);
Packit fabffb
Packit fabffb
	dclass = get_device_class (device, applet);
Packit fabffb
	g_assert (dclass);
Packit fabffb
	if (!dclass->new_auto_connection (device, dclass_data,
Packit fabffb
	                                  applet_menu_item_activate_helper_new_connection,
Packit fabffb
	                                  info))
Packit fabffb
		applet_item_activate_info_destroy (info);
Packit fabffb
}
Packit fabffb
Packit fabffb
void
Packit fabffb
applet_menu_item_add_complex_separator_helper (GtkWidget *menu,
Packit fabffb
                                               NMApplet *applet,
Packit fabffb
                                               const gchar *label)
Packit fabffb
{
Packit fabffb
	GtkWidget *menu_item, *box, *xlabel, *separator;
Packit fabffb
Packit fabffb
	if (INDICATOR_ENABLED (applet)) {
Packit fabffb
		/* Indicator doesn't draw complex separators */
Packit fabffb
		return;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	menu_item = gtk_menu_item_new ();
Packit fabffb
	box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
Packit fabffb
Packit fabffb
	if (label) {
Packit fabffb
		xlabel = gtk_label_new (NULL);
Packit fabffb
		gtk_label_set_markup (GTK_LABEL (xlabel), label);
Packit fabffb
Packit fabffb
		separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
Packit fabffb
		g_object_set (G_OBJECT (separator), "valign", GTK_ALIGN_CENTER, NULL);
Packit fabffb
		gtk_box_pack_start (GTK_BOX (box), separator, TRUE, TRUE, 0);
Packit fabffb
Packit fabffb
		gtk_box_pack_start (GTK_BOX (box), xlabel, FALSE, FALSE, 2);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
Packit fabffb
	g_object_set (G_OBJECT (separator), "valign", GTK_ALIGN_CENTER, NULL);
Packit fabffb
	gtk_box_pack_start (GTK_BOX (box), separator, TRUE, TRUE, 0);
Packit fabffb
Packit fabffb
	g_object_set (G_OBJECT (menu_item),
Packit fabffb
		          "child", box,
Packit fabffb
		          "sensitive", FALSE,
Packit fabffb
		          NULL);
Packit fabffb
Packit fabffb
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
Packit fabffb
}
Packit fabffb
Packit fabffb
GtkWidget *
Packit fabffb
applet_new_menu_item_helper (NMConnection *connection,
Packit fabffb
                             NMConnection *active,
Packit fabffb
                             gboolean add_active)
Packit fabffb
{
Packit fabffb
	GtkWidget *item = gtk_menu_item_new_with_label ("");
Packit fabffb
Packit fabffb
	if (add_active && (active == connection)) {
Packit fabffb
		char *markup;
Packit fabffb
		GtkWidget *label;
Packit fabffb
Packit fabffb
		/* Pure evil */
Packit fabffb
		label = gtk_bin_get_child (GTK_BIN (item));
Packit fabffb
		gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
Packit fabffb
		markup = g_markup_printf_escaped ("%s", nm_connection_get_id (connection));
Packit fabffb
		gtk_label_set_markup (GTK_LABEL (label), markup);
Packit fabffb
		g_free (markup);
Packit fabffb
	} else
Packit fabffb
		gtk_menu_item_set_label (GTK_MENU_ITEM (item), nm_connection_get_id (connection));
Packit fabffb
Packit fabffb
	return item;
Packit fabffb
}
Packit fabffb
Packit fabffb
#define TITLE_TEXT_R ((double) 0x5e / 255.0 )
Packit fabffb
#define TITLE_TEXT_G ((double) 0x5e / 255.0 )
Packit fabffb
#define TITLE_TEXT_B ((double) 0x5e / 255.0 )
Packit fabffb
Packit fabffb
static void
Packit fabffb
menu_item_draw_generic (GtkWidget *widget, cairo_t *cr)
Packit fabffb
{
Packit fabffb
	GtkWidget *label;
Packit fabffb
	PangoFontDescription *desc;
Packit fabffb
	PangoLayout *layout;
Packit fabffb
	GtkStyleContext *style;
Packit fabffb
	int width = 0, height = 0, owidth, oheight;
Packit fabffb
	gdouble extraheight = 0, extrawidth = 0;
Packit fabffb
	const char *text;
Packit fabffb
	gdouble xpadding = 10.0;
Packit fabffb
	gdouble ypadding = 5.0;
Packit fabffb
	gdouble postpadding = 0.0;
Packit fabffb
Packit fabffb
	label = gtk_bin_get_child (GTK_BIN (widget));
Packit fabffb
	text = gtk_label_get_text (GTK_LABEL (label));
Packit fabffb
Packit fabffb
	layout = pango_cairo_create_layout (cr);
Packit fabffb
	style = gtk_widget_get_style_context (widget);
Packit fabffb
	gtk_style_context_get (style, gtk_style_context_get_state (style),
Packit fabffb
	                       "font", &desc,
Packit fabffb
	                       NULL);
Packit fabffb
	pango_font_description_set_variant (desc, PANGO_VARIANT_SMALL_CAPS);
Packit fabffb
	pango_font_description_set_weight (desc, PANGO_WEIGHT_SEMIBOLD);
Packit fabffb
	pango_layout_set_font_description (layout, desc);
Packit fabffb
	pango_layout_set_text (layout, text, -1);
Packit fabffb
	pango_cairo_update_layout (cr, layout);
Packit fabffb
	pango_layout_get_size (layout, &owidth, &oheight);
Packit fabffb
	width = owidth / PANGO_SCALE;
Packit fabffb
	height += oheight / PANGO_SCALE;
Packit fabffb
Packit fabffb
	cairo_save (cr);
Packit fabffb
Packit fabffb
	cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0);
Packit fabffb
	cairo_rectangle (cr, 0, 0,
Packit fabffb
	                 (double) (width + 2 * xpadding),
Packit fabffb
	                 (double) (height + ypadding + postpadding));
Packit fabffb
	cairo_fill (cr);
Packit fabffb
Packit fabffb
	/* now the in-padding content */
Packit fabffb
	cairo_translate (cr, xpadding , ypadding);
Packit fabffb
	cairo_set_source_rgb (cr, TITLE_TEXT_R, TITLE_TEXT_G, TITLE_TEXT_B);
Packit fabffb
	cairo_move_to (cr, extrawidth, extraheight);
Packit fabffb
	pango_cairo_show_layout (cr, layout);
Packit fabffb
Packit fabffb
	cairo_restore(cr);
Packit fabffb
Packit fabffb
	pango_font_description_free (desc);
Packit fabffb
	g_object_unref (layout);
Packit fabffb
Packit fabffb
	gtk_widget_set_size_request (widget, width + 2 * xpadding, height + ypadding + postpadding);
Packit fabffb
}
Packit fabffb
Packit fabffb
static gboolean
Packit fabffb
menu_title_item_draw (GtkWidget *widget, cairo_t *cr, gpointer user_data)
Packit fabffb
{
Packit fabffb
	menu_item_draw_generic (widget, cr);
Packit fabffb
	return TRUE;
Packit fabffb
}
Packit fabffb
Packit fabffb
GtkWidget *
Packit fabffb
applet_menu_item_create_device_item_helper (NMDevice *device,
Packit fabffb
                                            NMApplet *applet,
Packit fabffb
                                            const gchar *text)
Packit fabffb
{
Packit fabffb
	GtkWidget *item;
Packit fabffb
Packit fabffb
	item = gtk_menu_item_new_with_label (text);
Packit fabffb
	gtk_widget_set_sensitive (item, FALSE);
Packit fabffb
	if (!INDICATOR_ENABLED (applet))
Packit fabffb
		g_signal_connect (item, "draw", G_CALLBACK (menu_title_item_draw), NULL);
Packit fabffb
	return item;
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_clear_notify (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	if (applet->notification == NULL)
Packit fabffb
		return;
Packit fabffb
Packit fabffb
	notify_notification_close (applet->notification, NULL);
Packit fabffb
	g_object_unref (applet->notification);
Packit fabffb
	applet->notification = NULL;
Packit fabffb
}
Packit fabffb
Packit fabffb
static gboolean
Packit fabffb
applet_notify_server_has_actions (void)
Packit fabffb
{
Packit fabffb
	static gboolean has_actions = FALSE;
Packit fabffb
	static gboolean initialized = FALSE;
Packit fabffb
	GList *server_caps, *iter;
Packit fabffb
Packit fabffb
	if (initialized)
Packit fabffb
		return has_actions;
Packit fabffb
	initialized = TRUE;
Packit fabffb
Packit fabffb
	server_caps = notify_get_server_caps();
Packit fabffb
	for (iter = server_caps; iter; iter = g_list_next (iter)) {
Packit fabffb
		if (!strcmp ((const char *) iter->data, NOTIFY_CAPS_ACTIONS_KEY)) {
Packit fabffb
			has_actions = TRUE;
Packit fabffb
			break;
Packit fabffb
		}
Packit fabffb
	}
Packit fabffb
	g_list_free_full (server_caps, g_free);
Packit fabffb
Packit fabffb
	return has_actions;
Packit fabffb
}
Packit fabffb
Packit fabffb
void
Packit fabffb
applet_do_notify (NMApplet *applet,
Packit fabffb
                  NotifyUrgency urgency,
Packit fabffb
                  const char *summary,
Packit fabffb
                  const char *message,
Packit fabffb
                  const char *icon,
Packit fabffb
                  const char *action1,
Packit fabffb
                  const char *action1_label,
Packit fabffb
                  NotifyActionCallback action1_cb,
Packit fabffb
                  gpointer action1_user_data)
Packit fabffb
{
Packit fabffb
	NotifyNotification *notify;
Packit fabffb
	GError *error = NULL;
Packit fabffb
	char *escaped;
Packit fabffb
Packit fabffb
	g_return_if_fail (applet != NULL);
Packit fabffb
	g_return_if_fail (summary != NULL);
Packit fabffb
	g_return_if_fail (message != NULL);
Packit fabffb
Packit fabffb
	if (INDICATOR_ENABLED (applet)) {
Packit fabffb
#ifdef WITH_APPINDICATOR
Packit fabffb
		if (app_indicator_get_status (applet->app_indicator) == APP_INDICATOR_STATUS_PASSIVE)
Packit fabffb
			return;
Packit fabffb
#endif  /* WITH_APPINDICATOR */
Packit fabffb
	} else {
Packit fabffb
		if (!gtk_status_icon_is_embedded (applet->status_icon))
Packit fabffb
			return;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	/* if we're not acting as a secret agent, don't notify either */
Packit fabffb
	if (!applet->agent)
Packit fabffb
		return;
Packit fabffb
Packit fabffb
	applet_clear_notify (applet);
Packit fabffb
Packit fabffb
	escaped = utils_escape_notify_message (message);
Packit fabffb
	notify = notify_notification_new (summary,
Packit fabffb
	                                  escaped,
Packit fabffb
	                                  icon ? icon : "network-workgroup"
Packit fabffb
#if HAVE_LIBNOTIFY_07
Packit fabffb
	                                  );
Packit fabffb
#else
Packit fabffb
	                                  , NULL);
Packit fabffb
#endif
Packit fabffb
	g_free (escaped);
Packit fabffb
	applet->notification = notify;
Packit fabffb
Packit fabffb
#if HAVE_LIBNOTIFY_07
Packit fabffb
	notify_notification_set_hint (notify, "transient", g_variant_new_boolean (TRUE));
Packit fabffb
	notify_notification_set_hint (notify, "desktop-entry", g_variant_new_string ("nm-applet"));
Packit fabffb
#else
Packit fabffb
	notify_notification_attach_to_status_icon (notify, applet->status_icon);
Packit fabffb
#endif
Packit fabffb
	notify_notification_set_urgency (notify, urgency);
Packit fabffb
	notify_notification_set_timeout (notify, NOTIFY_EXPIRES_DEFAULT);
Packit fabffb
Packit fabffb
	if (applet_notify_server_has_actions () && action1) {
Packit fabffb
		notify_notification_clear_actions (notify);
Packit fabffb
		notify_notification_add_action (notify, action1, action1_label,
Packit fabffb
		                                action1_cb, action1_user_data, NULL);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	if (!notify_notification_show (notify, &error)) {
Packit fabffb
		g_warning ("Failed to show notification: %s",
Packit fabffb
		           error && error->message ? error->message : "(unknown)");
Packit fabffb
		g_clear_error (&error);
Packit fabffb
	}
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
notify_dont_show_cb (NotifyNotification *notify,
Packit fabffb
                     gchar *id,
Packit fabffb
                     gpointer user_data)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (user_data);
Packit fabffb
Packit fabffb
	if (!id)
Packit fabffb
		return;
Packit fabffb
Packit fabffb
	if (   strcmp (id, PREF_DISABLE_CONNECTED_NOTIFICATIONS)
Packit fabffb
	    && strcmp (id, PREF_DISABLE_DISCONNECTED_NOTIFICATIONS)
Packit fabffb
	    && strcmp (id, PREF_DISABLE_VPN_NOTIFICATIONS))
Packit fabffb
		return;
Packit fabffb
Packit fabffb
	g_settings_set_boolean (applet->gsettings, id, TRUE);
Packit fabffb
}
Packit fabffb
Packit fabffb
void applet_do_notify_with_pref (NMApplet *applet,
Packit fabffb
                                 const char *summary,
Packit fabffb
                                 const char *message,
Packit fabffb
                                 const char *icon,
Packit fabffb
                                 const char *pref)
Packit fabffb
{
Packit fabffb
	if (g_settings_get_boolean (applet->gsettings, pref))
Packit fabffb
		return;
Packit fabffb
Packit fabffb
	applet_do_notify (applet, NOTIFY_URGENCY_LOW, summary, message, icon, pref,
Packit fabffb
	                  _("Don’t show this message again"),
Packit fabffb
	                  notify_dont_show_cb,
Packit fabffb
	                  applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
static gboolean
Packit fabffb
animation_timeout (gpointer data)
Packit fabffb
{
Packit fabffb
	applet_schedule_update_icon (NM_APPLET (data));
Packit fabffb
	return TRUE;
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
start_animation_timeout (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	if (applet->animation_id == 0) {
Packit fabffb
		applet->animation_step = 0;
Packit fabffb
		applet->animation_id = g_timeout_add (100, animation_timeout, applet);
Packit fabffb
	}
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
clear_animation_timeout (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	if (applet->animation_id) {
Packit fabffb
		g_source_remove (applet->animation_id);
Packit fabffb
		applet->animation_id = 0;
Packit fabffb
		applet->animation_step = 0;
Packit fabffb
	}
Packit fabffb
}
Packit fabffb
Packit fabffb
static gboolean
Packit fabffb
applet_is_any_device_activating (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	const GPtrArray *devices;
Packit fabffb
	int i;
Packit fabffb
Packit fabffb
	/* Check for activating devices */
Packit fabffb
	devices = nm_client_get_devices (applet->nm_client);
Packit fabffb
	for (i = 0; devices && (i < devices->len); i++) {
Packit fabffb
		NMDevice *candidate = NM_DEVICE (g_ptr_array_index (devices, i));
Packit fabffb
		NMDeviceState state;
Packit fabffb
Packit fabffb
		state = nm_device_get_state (candidate);
Packit fabffb
		if (state > NM_DEVICE_STATE_DISCONNECTED && state < NM_DEVICE_STATE_ACTIVATED)
Packit fabffb
			return TRUE;
Packit fabffb
	}
Packit fabffb
	return FALSE;
Packit fabffb
}
Packit fabffb
Packit fabffb
static gboolean
Packit fabffb
applet_is_any_vpn_activating (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	const GPtrArray *connections;
Packit fabffb
	int i;
Packit fabffb
Packit fabffb
	connections = nm_client_get_active_connections (applet->nm_client);
Packit fabffb
	for (i = 0; connections && (i < connections->len); i++) {
Packit fabffb
		NMActiveConnection *candidate = NM_ACTIVE_CONNECTION (g_ptr_array_index (connections, i));
Packit fabffb
		NMActiveConnectionState state;
Packit fabffb
Packit fabffb
		if (NM_IS_VPN_CONNECTION (candidate)) {
Packit fabffb
			state = nm_active_connection_get_state (candidate);
Packit fabffb
			if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING)
Packit fabffb
				return TRUE;
Packit fabffb
		}
Packit fabffb
	}
Packit fabffb
	return FALSE;
Packit fabffb
}
Packit fabffb
Packit fabffb
static char *
Packit fabffb
make_active_failure_message (NMActiveConnection *active,
Packit fabffb
                             NMActiveConnectionStateReason reason,
Packit fabffb
                             NMApplet *applet)
Packit fabffb
{
Packit fabffb
	NMConnection *connection;
Packit fabffb
	const GPtrArray *devices;
Packit fabffb
	NMDevice *device;
Packit fabffb
	const char *id;
Packit fabffb
Packit fabffb
	g_return_val_if_fail (active != NULL, NULL);
Packit fabffb
Packit fabffb
	connection = (NMConnection *) nm_active_connection_get_connection (active);
Packit fabffb
	id = nm_connection_get_id (connection);
Packit fabffb
Packit fabffb
	switch (reason) {
Packit fabffb
	case NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED:
Packit fabffb
		devices = nm_active_connection_get_devices (active);
Packit fabffb
		device = devices && devices->len > 0 ? devices->pdata[0] : NULL;
Packit fabffb
		if (device && nm_device_get_state (device) == NM_DEVICE_STATE_DISCONNECTED)
Packit fabffb
			return g_strdup_printf (_("\nThe VPN connection “%s” disconnected because the network connection was interrupted."), id);
Packit fabffb
		else
Packit fabffb
			return g_strdup_printf (_("\nThe VPN connection “%s” failed because the network connection was interrupted."), id);
Packit fabffb
	case NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_STOPPED:
Packit fabffb
		return g_strdup_printf (_("\nThe VPN connection “%s” failed because the VPN service stopped unexpectedly."), id);
Packit fabffb
	case NM_ACTIVE_CONNECTION_STATE_REASON_IP_CONFIG_INVALID:
Packit fabffb
		return g_strdup_printf (_("\nThe VPN connection “%s” failed because the VPN service returned invalid configuration."), id);
Packit fabffb
	case NM_ACTIVE_CONNECTION_STATE_REASON_CONNECT_TIMEOUT:
Packit fabffb
		return g_strdup_printf (_("\nThe VPN connection “%s” failed because the connection attempt timed out."), id);
Packit fabffb
	case NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT:
Packit fabffb
		return g_strdup_printf (_("\nThe VPN connection “%s” failed because the VPN service did not start in time."), id);
Packit fabffb
	case NM_ACTIVE_CONNECTION_STATE_REASON_SERVICE_START_FAILED:
Packit fabffb
		return g_strdup_printf (_("\nThe VPN connection “%s” failed because the VPN service failed to start."), id);
Packit fabffb
	case NM_ACTIVE_CONNECTION_STATE_REASON_NO_SECRETS:
Packit fabffb
		return g_strdup_printf (_("\nThe VPN connection “%s” failed because there were no valid VPN secrets."), id);
Packit fabffb
	case NM_ACTIVE_CONNECTION_STATE_REASON_LOGIN_FAILED:
Packit fabffb
		return g_strdup_printf (_("\nThe VPN connection “%s” failed because of invalid VPN secrets."), id);
Packit fabffb
	default:
Packit fabffb
		break;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	return g_strdup_printf (_("\nThe VPN connection “%s” failed."), id);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
vpn_active_connection_state_changed (NMVpnConnection *vpn,
Packit fabffb
                                     NMActiveConnectionState state,
Packit fabffb
                                     NMActiveConnectionStateReason reason,
Packit fabffb
                                     gpointer user_data)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (user_data);
Packit fabffb
	const char *banner;
Packit fabffb
	char *title = NULL, *msg;
Packit fabffb
	gboolean device_activating, vpn_activating;
Packit fabffb
Packit fabffb
	device_activating = applet_is_any_device_activating (applet);
Packit fabffb
	vpn_activating = applet_is_any_vpn_activating (applet);
Packit fabffb
Packit fabffb
	switch (state) {
Packit fabffb
	case NM_ACTIVE_CONNECTION_STATE_ACTIVATING:
Packit fabffb
		/* Be sure to turn animation timeout on here since the dbus signals
Packit fabffb
		 * for new active connections might not have come through yet.
Packit fabffb
		 */
Packit fabffb
		vpn_activating = TRUE;
Packit fabffb
		break;
Packit fabffb
	case NM_ACTIVE_CONNECTION_STATE_ACTIVATED:
Packit fabffb
		banner = nm_vpn_connection_get_banner (vpn);
Packit fabffb
		if (banner && strlen (banner))
Packit fabffb
			msg = g_strdup_printf (_("VPN connection has been successfully established.\n\n%s\n"), banner);
Packit fabffb
		else
Packit fabffb
			msg = g_strdup (_("VPN connection has been successfully established.\n"));
Packit fabffb
Packit fabffb
		title = _("VPN Login Message");
Packit fabffb
		applet_do_notify_with_pref (applet, title, msg, "gnome-lockscreen",
Packit fabffb
		                            PREF_DISABLE_VPN_NOTIFICATIONS);
Packit fabffb
		g_free (msg);
Packit fabffb
		break;
Packit fabffb
	case NM_ACTIVE_CONNECTION_STATE_DEACTIVATED:
Packit fabffb
		if (reason == NM_ACTIVE_CONNECTION_STATE_REASON_USER_DISCONNECTED)
Packit fabffb
			break;
Packit fabffb
		title = _("VPN Connection Failed");
Packit fabffb
		msg = make_active_failure_message (NM_ACTIVE_CONNECTION (vpn), reason, applet);
Packit fabffb
		applet_do_notify_with_pref (applet, title, msg, "gnome-lockscreen",
Packit fabffb
		                            PREF_DISABLE_VPN_NOTIFICATIONS);
Packit fabffb
		g_free (msg);
Packit fabffb
		break;
Packit fabffb
	default:
Packit fabffb
		break;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	if (device_activating || vpn_activating)
Packit fabffb
		start_animation_timeout (applet);
Packit fabffb
	else
Packit fabffb
		clear_animation_timeout (applet);
Packit fabffb
Packit fabffb
	applet_schedule_update_icon (applet);
Packit fabffb
	applet_schedule_update_menu (applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
typedef struct {
Packit fabffb
	NMApplet *applet;
Packit fabffb
	char *vpn_name;
Packit fabffb
} VPNActivateInfo;
Packit fabffb
Packit fabffb
static void
Packit fabffb
activate_vpn_cb (GObject *client,
Packit fabffb
                 GAsyncResult *result,
Packit fabffb
                 gpointer user_data)
Packit fabffb
{
Packit fabffb
	VPNActivateInfo *info = (VPNActivateInfo *) user_data;
Packit fabffb
	NMActiveConnection *active;
Packit fabffb
	char *title, *msg, *name;
Packit fabffb
	GError *error = NULL;
Packit fabffb
Packit fabffb
	active = nm_client_activate_connection_finish (NM_CLIENT (client), result, &error);
Packit fabffb
	g_clear_object (&active);
Packit fabffb
Packit fabffb
	if (error) {
Packit fabffb
		clear_animation_timeout (info->applet);
Packit fabffb
Packit fabffb
		title = _("VPN Connection Failed");
Packit fabffb
Packit fabffb
		name = g_dbus_error_get_remote_error (error);
Packit fabffb
		if (name && strstr (name, "ServiceStartFailed")) {
Packit fabffb
			msg = g_strdup_printf (_("\nThe VPN connection “%s” failed because the VPN service failed to start.\n\n%s"),
Packit fabffb
			                       info->vpn_name, error->message);
Packit fabffb
		} else {
Packit fabffb
			msg = g_strdup_printf (_("\nThe VPN connection “%s” failed to start.\n\n%s"),
Packit fabffb
			                       info->vpn_name, error->message);
Packit fabffb
		}
Packit fabffb
Packit fabffb
		applet_do_notify_with_pref (info->applet, title, msg, "gnome-lockscreen",
Packit fabffb
		                            PREF_DISABLE_VPN_NOTIFICATIONS);
Packit fabffb
		g_warning ("VPN Connection activation failed: (%s) %s", name, error->message);
Packit fabffb
		g_free (msg);
Packit fabffb
		g_free (name);
Packit fabffb
		g_error_free (error);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	applet_schedule_update_icon (info->applet);
Packit fabffb
	applet_schedule_update_menu (info->applet);
Packit fabffb
	g_free (info->vpn_name);
Packit fabffb
	g_free (info);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
nma_menu_vpn_item_clicked (GtkMenuItem *item, gpointer user_data)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (user_data);
Packit fabffb
	VPNActivateInfo *info;
Packit fabffb
	NMConnection *connection;
Packit fabffb
	NMActiveConnection *active;
Packit fabffb
	NMDevice *device = NULL;
Packit fabffb
Packit fabffb
	connection = NM_CONNECTION (g_object_get_data (G_OBJECT (item), "connection"));
Packit fabffb
	if (!connection) {
Packit fabffb
		g_warning ("%s: no connection associated with menu item!", __func__);
Packit fabffb
		return;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	active = applet_get_active_for_connection (applet, connection);
Packit fabffb
	if (active) {
Packit fabffb
		/* Connection already active; disconnect it */
Packit fabffb
		nm_client_deactivate_connection (applet->nm_client, active, NULL, NULL);
Packit fabffb
		return;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	active = applet_get_default_active_connection (applet, &device, FALSE);
Packit fabffb
	if (!active || !device) {
Packit fabffb
		g_warning ("%s: no active connection or device.", __func__);
Packit fabffb
		return;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	info = g_malloc0 (sizeof (VPNActivateInfo));
Packit fabffb
	info->applet = applet;
Packit fabffb
	info->vpn_name = g_strdup (nm_connection_get_id (connection));
Packit fabffb
Packit fabffb
	/* Connection inactive, activate */
Packit fabffb
	nm_client_activate_connection_async (applet->nm_client,
Packit fabffb
	                                     connection,
Packit fabffb
	                                     device,
Packit fabffb
	                                     nm_object_get_path (NM_OBJECT (active)),
Packit fabffb
	                                     NULL,
Packit fabffb
	                                     activate_vpn_cb,
Packit fabffb
	                                     info);
Packit fabffb
	start_animation_timeout (applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
Packit fabffb
/*
Packit fabffb
 * nma_menu_configure_vpn_item_activate
Packit fabffb
 *
Packit fabffb
 * Signal function called when user clicks "Configure VPN..."
Packit fabffb
 *
Packit fabffb
 */
Packit fabffb
static void
Packit fabffb
nma_menu_configure_vpn_item_activate (GtkMenuItem *item, gpointer user_data)
Packit fabffb
{
Packit fabffb
	const char *argv[] = { BINDIR "/nm-connection-editor", "--show", "--type", NM_SETTING_VPN_SETTING_NAME, NULL};
Packit fabffb
Packit fabffb
	g_spawn_async (NULL, (gchar **) argv, NULL, 0, NULL, NULL, NULL, NULL);
Packit fabffb
}
Packit fabffb
Packit fabffb
/*
Packit fabffb
 * nma_menu_add_vpn_item_activate
Packit fabffb
 *
Packit fabffb
 * Signal function called when user clicks "Add a VPN connection..."
Packit fabffb
 *
Packit fabffb
 */
Packit fabffb
static void
Packit fabffb
nma_menu_add_vpn_item_activate (GtkMenuItem *item, gpointer user_data)
Packit fabffb
{
Packit fabffb
	const char *argv[] = { BINDIR "/nm-connection-editor", "--create", "--type", NM_SETTING_VPN_SETTING_NAME, NULL};
Packit fabffb
Packit fabffb
	g_spawn_async (NULL, (gchar **) argv, NULL, 0, NULL, NULL, NULL, NULL);
Packit fabffb
}
Packit fabffb
Packit fabffb
/*
Packit fabffb
 * applet_get_active_vpn_connection:
Packit fabffb
 *
Packit fabffb
 * Gets a VPN connection along with its state. If there are more, ones that
Packit fabffb
 * are not yet fully activated are preferred.
Packit fabffb
 *
Packit fabffb
 */
Packit fabffb
static NMActiveConnection *
Packit fabffb
applet_get_active_vpn_connection (NMApplet *applet,
Packit fabffb
                                        NMVpnConnectionState *out_state)
Packit fabffb
{
Packit fabffb
	const GPtrArray *active_list;
Packit fabffb
	NMActiveConnection *ret = NULL;
Packit fabffb
	NMVpnConnectionState state = NM_VPN_CONNECTION_STATE_UNKNOWN;
Packit fabffb
	int i;
Packit fabffb
Packit fabffb
	active_list = nm_client_get_active_connections (applet->nm_client);
Packit fabffb
	for (i = 0; active_list && (i < active_list->len); i++) {
Packit fabffb
		NMActiveConnection *candidate;
Packit fabffb
		NMConnection *connection;
Packit fabffb
		NMSettingConnection *s_con;
Packit fabffb
Packit fabffb
		candidate = g_ptr_array_index (active_list, i);
Packit fabffb
Packit fabffb
		connection = (NMConnection *) nm_active_connection_get_connection (candidate);
Packit fabffb
		if (!connection)
Packit fabffb
			continue;
Packit fabffb
Packit fabffb
		s_con = nm_connection_get_setting_connection (connection);
Packit fabffb
		if (!s_con)
Packit fabffb
			continue;
Packit fabffb
Packit fabffb
		if (!strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_VPN_SETTING_NAME)) {
Packit fabffb
			ret = candidate;
Packit fabffb
			state = nm_vpn_connection_get_vpn_state (NM_VPN_CONNECTION (candidate));
Packit fabffb
Packit fabffb
			if (state != NM_VPN_CONNECTION_STATE_ACTIVATED)
Packit fabffb
				break;
Packit fabffb
		}
Packit fabffb
	}
Packit fabffb
Packit fabffb
	if (ret && out_state)
Packit fabffb
		*out_state = state;
Packit fabffb
Packit fabffb
	return ret;
Packit fabffb
}
Packit fabffb
Packit fabffb
/*
Packit fabffb
 * nma_menu_add_separator_item
Packit fabffb
 *
Packit fabffb
 */
Packit fabffb
static void
Packit fabffb
nma_menu_add_separator_item (GtkWidget *menu)
Packit fabffb
{
Packit fabffb
	GtkWidget *menu_item;
Packit fabffb
Packit fabffb
	menu_item = gtk_separator_menu_item_new ();
Packit fabffb
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
Packit fabffb
	gtk_widget_show (menu_item);
Packit fabffb
}
Packit fabffb
Packit fabffb
Packit fabffb
/*
Packit fabffb
 * nma_menu_add_text_item
Packit fabffb
 *
Packit fabffb
 * Add a non-clickable text item to a menu
Packit fabffb
 *
Packit fabffb
 */
Packit fabffb
static void nma_menu_add_text_item (GtkWidget *menu, char *text)
Packit fabffb
{
Packit fabffb
	GtkWidget		*menu_item;
Packit fabffb
Packit fabffb
	g_return_if_fail (text != NULL);
Packit fabffb
	g_return_if_fail (menu != NULL);
Packit fabffb
Packit fabffb
	menu_item = gtk_menu_item_new_with_label (text);
Packit fabffb
	gtk_widget_set_sensitive (menu_item, FALSE);
Packit fabffb
Packit fabffb
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
Packit fabffb
	gtk_widget_show (menu_item);
Packit fabffb
}
Packit fabffb
Packit fabffb
static gint
Packit fabffb
sort_devices_by_description (gconstpointer a, gconstpointer b)
Packit fabffb
{
Packit fabffb
	NMDevice *aa = NM_DEVICE (a);
Packit fabffb
	NMDevice *bb = NM_DEVICE (b);
Packit fabffb
	const char *aa_desc;
Packit fabffb
	const char *bb_desc;
Packit fabffb
Packit fabffb
	aa_desc = nm_device_get_description (aa);
Packit fabffb
	bb_desc = nm_device_get_description (bb);
Packit fabffb
Packit fabffb
	return g_strcmp0 (aa_desc, bb_desc);
Packit fabffb
}
Packit fabffb
Packit fabffb
static gboolean
Packit fabffb
nm_g_ptr_array_contains (const GPtrArray *haystack, gpointer needle)
Packit fabffb
{
Packit fabffb
	int i;
Packit fabffb
Packit fabffb
	for (i = 0; haystack && (i < haystack->len); i++) {
Packit fabffb
		if (g_ptr_array_index (haystack, i) == needle)
Packit fabffb
			return TRUE;
Packit fabffb
	}
Packit fabffb
	return FALSE;
Packit fabffb
}
Packit fabffb
Packit fabffb
static NMConnection *
Packit fabffb
applet_find_active_connection_for_device (NMDevice *device,
Packit fabffb
                                          NMApplet *applet,
Packit fabffb
                                          NMActiveConnection **out_active)
Packit fabffb
{
Packit fabffb
	const GPtrArray *active_connections;
Packit fabffb
	int i;
Packit fabffb
Packit fabffb
	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
Packit fabffb
	g_return_val_if_fail (NM_IS_APPLET (applet), NULL);
Packit fabffb
	if (out_active)
Packit fabffb
		g_return_val_if_fail (*out_active == NULL, NULL);
Packit fabffb
Packit fabffb
	active_connections = nm_client_get_active_connections (applet->nm_client);
Packit fabffb
	for (i = 0; i < active_connections->len; i++) {
Packit fabffb
		NMRemoteConnection *conn;
Packit fabffb
		NMActiveConnection *active;
Packit fabffb
		const GPtrArray *devices;
Packit fabffb
Packit fabffb
		active = NM_ACTIVE_CONNECTION (g_ptr_array_index (active_connections, i));
Packit fabffb
		devices = nm_active_connection_get_devices (active);
Packit fabffb
		conn = nm_active_connection_get_connection (active);
Packit fabffb
Packit fabffb
		/* Skip VPN connections */
Packit fabffb
		if (nm_active_connection_get_vpn (active))
Packit fabffb
			continue;
Packit fabffb
Packit fabffb
		if (!devices || !conn)
Packit fabffb
			continue;
Packit fabffb
Packit fabffb
		if (!nm_g_ptr_array_contains (devices, device))
Packit fabffb
			continue;
Packit fabffb
Packit fabffb
		if (out_active)
Packit fabffb
			*out_active = active;
Packit fabffb
		return NM_CONNECTION (conn);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	return NULL;
Packit fabffb
}
Packit fabffb
Packit fabffb
gboolean
Packit fabffb
nma_menu_device_check_unusable (NMDevice *device)
Packit fabffb
{
Packit fabffb
	switch (nm_device_get_state (device)) {
Packit fabffb
	case NM_DEVICE_STATE_UNKNOWN:
Packit fabffb
	case NM_DEVICE_STATE_UNAVAILABLE:
Packit fabffb
	case NM_DEVICE_STATE_UNMANAGED:
Packit fabffb
		return TRUE;
Packit fabffb
	default:
Packit fabffb
		break;
Packit fabffb
	}
Packit fabffb
	return FALSE;
Packit fabffb
}
Packit fabffb
Packit fabffb
Packit fabffb
struct AppletDeviceMenuInfo {
Packit fabffb
	NMDevice *device;
Packit fabffb
	NMApplet *applet;
Packit fabffb
};
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_device_info_destroy (gpointer data, GClosure *closure)
Packit fabffb
{
Packit fabffb
	struct AppletDeviceMenuInfo *info = data;
Packit fabffb
Packit fabffb
	g_return_if_fail (info != NULL);
Packit fabffb
Packit fabffb
	if (info->device)
Packit fabffb
		g_object_unref (info->device);
Packit fabffb
	memset (info, 0, sizeof (struct AppletDeviceMenuInfo));
Packit fabffb
	g_free (info);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_device_disconnect_db (GtkMenuItem *item, gpointer user_data)
Packit fabffb
{
Packit fabffb
	struct AppletDeviceMenuInfo *info = user_data;
Packit fabffb
Packit fabffb
	applet_menu_item_disconnect_helper (info->device,
Packit fabffb
	                                    info->applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
GtkWidget *
Packit fabffb
nma_menu_device_get_menu_item (NMDevice *device,
Packit fabffb
                               NMApplet *applet,
Packit fabffb
                               const char *unavailable_msg)
Packit fabffb
{
Packit fabffb
	GtkWidget *item = NULL;
Packit fabffb
	gboolean managed = TRUE;
Packit fabffb
Packit fabffb
	if (!unavailable_msg) {
Packit fabffb
		if (nm_device_get_firmware_missing (device))
Packit fabffb
			unavailable_msg = _("device not ready (firmware missing)");
Packit fabffb
		else
Packit fabffb
			unavailable_msg = _("device not ready");
Packit fabffb
	}
Packit fabffb
Packit fabffb
	switch (nm_device_get_state (device)) {
Packit fabffb
	case NM_DEVICE_STATE_UNKNOWN:
Packit fabffb
	case NM_DEVICE_STATE_UNAVAILABLE:
Packit fabffb
		item = gtk_menu_item_new_with_label (unavailable_msg);
Packit fabffb
		gtk_widget_set_sensitive (item, FALSE);
Packit fabffb
		break;
Packit fabffb
	case NM_DEVICE_STATE_DISCONNECTED:
Packit fabffb
		unavailable_msg = _("disconnected");
Packit fabffb
		item = gtk_menu_item_new_with_label (unavailable_msg);
Packit fabffb
		gtk_widget_set_sensitive (item, FALSE);
Packit fabffb
		break;
Packit fabffb
	case NM_DEVICE_STATE_UNMANAGED:
Packit fabffb
		managed = FALSE;
Packit fabffb
		break;
Packit fabffb
	case NM_DEVICE_STATE_PREPARE:
Packit fabffb
	case NM_DEVICE_STATE_CONFIG:
Packit fabffb
	case NM_DEVICE_STATE_NEED_AUTH:
Packit fabffb
	case NM_DEVICE_STATE_IP_CONFIG:
Packit fabffb
	case NM_DEVICE_STATE_ACTIVATED:
Packit fabffb
	{
Packit fabffb
		struct AppletDeviceMenuInfo *info = g_new0 (struct AppletDeviceMenuInfo, 1);
Packit fabffb
		info->device = g_object_ref (device);
Packit fabffb
		info->applet = applet;
Packit fabffb
		item = gtk_menu_item_new_with_label (_("Disconnect"));
Packit fabffb
		g_signal_connect_data (item, "activate",
Packit fabffb
		                       G_CALLBACK (applet_device_disconnect_db),
Packit fabffb
		                       info,
Packit fabffb
		                       applet_device_info_destroy, 0);
Packit fabffb
		gtk_widget_set_sensitive (item, TRUE);
Packit fabffb
		break;
Packit fabffb
	}
Packit fabffb
	default:
Packit fabffb
		managed = nm_device_get_managed (device);
Packit fabffb
		break;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	if (!managed) {
Packit fabffb
		item = gtk_menu_item_new_with_label (_("device not managed"));
Packit fabffb
		gtk_widget_set_sensitive (item, FALSE);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	return item;
Packit fabffb
}
Packit fabffb
Packit fabffb
static int
Packit fabffb
add_device_items (NMDeviceType type, const GPtrArray *all_devices,
Packit fabffb
                  const GPtrArray *all_connections,
Packit fabffb
                  GtkWidget *menu, NMApplet *applet)
Packit fabffb
{
Packit fabffb
	GSList *devices = NULL, *iter;
Packit fabffb
	int i, n_devices = 0;
Packit fabffb
Packit fabffb
	for (i = 0; all_devices && (i < all_devices->len); i++) {
Packit fabffb
		NMDevice *device = all_devices->pdata[i];
Packit fabffb
Packit fabffb
		if (nm_device_get_device_type (device) == type) {
Packit fabffb
			n_devices++;
Packit fabffb
			devices = g_slist_prepend (devices, device);
Packit fabffb
		}
Packit fabffb
	}
Packit fabffb
	devices = g_slist_sort (devices, sort_devices_by_description);
Packit fabffb
Packit fabffb
	for (iter = devices; iter; iter = iter->next) {
Packit fabffb
		NMDevice *device = iter->data;
Packit fabffb
		NMADeviceClass *dclass;
Packit fabffb
		NMConnection *active;
Packit fabffb
		GPtrArray *connections;
Packit fabffb
Packit fabffb
		dclass = get_device_class (device, applet);
Packit fabffb
		if (!dclass)
Packit fabffb
			continue;
Packit fabffb
Packit fabffb
		connections = nm_device_filter_connections (device, all_connections);
Packit fabffb
		active = applet_find_active_connection_for_device (device, applet, NULL);
Packit fabffb
Packit fabffb
		dclass->add_menu_item (device, n_devices > 1, connections, active, menu, applet);
Packit fabffb
Packit fabffb
		g_ptr_array_unref (connections);
Packit fabffb
Packit fabffb
		if (INDICATOR_ENABLED (applet))
Packit fabffb
			gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_separator_menu_item_new ());
Packit fabffb
	}
Packit fabffb
Packit fabffb
	g_slist_free (devices);
Packit fabffb
	return n_devices;
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
nma_menu_add_devices (GtkWidget *menu, NMApplet *applet)
Packit fabffb
{
Packit fabffb
	const GPtrArray *all_devices;
Packit fabffb
	GPtrArray *all_connections;
Packit fabffb
	gint n_items;
Packit fabffb
Packit fabffb
	all_connections = applet_get_all_connections (applet);
Packit fabffb
	all_devices = nm_client_get_devices (applet->nm_client);
Packit fabffb
Packit fabffb
	n_items = 0;
Packit fabffb
	n_items += add_device_items  (NM_DEVICE_TYPE_ETHERNET,
Packit fabffb
	                              all_devices, all_connections, menu, applet);
Packit fabffb
	n_items += add_device_items  (NM_DEVICE_TYPE_WIFI,
Packit fabffb
	                              all_devices, all_connections, menu, applet);
Packit fabffb
	n_items += add_device_items  (NM_DEVICE_TYPE_MODEM,
Packit fabffb
	                              all_devices, all_connections, menu, applet);
Packit fabffb
	n_items += add_device_items  (NM_DEVICE_TYPE_BT,
Packit fabffb
	                              all_devices, all_connections, menu, applet);
Packit fabffb
Packit fabffb
	g_ptr_array_unref (all_connections);
Packit fabffb
Packit fabffb
	if (!n_items)
Packit fabffb
		nma_menu_add_text_item (menu, _("No network devices available"));
Packit fabffb
}
Packit fabffb
Packit fabffb
static int
Packit fabffb
sort_vpn_connections (gconstpointer a, gconstpointer b)
Packit fabffb
{
Packit fabffb
	NMConnection **ca = (NMConnection **) a;
Packit fabffb
	NMConnection **cb = (NMConnection **) b;
Packit fabffb
Packit fabffb
	return strcmp (nm_connection_get_id (NM_CONNECTION (*ca)), nm_connection_get_id (NM_CONNECTION (*cb)));
Packit fabffb
}
Packit fabffb
Packit fabffb
static GPtrArray *
Packit fabffb
get_vpn_connections (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	GPtrArray *all_connections, *vpn_connections;
Packit fabffb
	int i;
Packit fabffb
Packit fabffb
	all_connections = applet_get_all_connections (applet);
Packit fabffb
	vpn_connections = g_ptr_array_new_full (5, g_object_unref);
Packit fabffb
Packit fabffb
	for (i = 0; i < all_connections->len; i++) {
Packit fabffb
		NMConnection *connection = NM_CONNECTION (all_connections->pdata[i]);
Packit fabffb
Packit fabffb
		if (!nm_connection_is_type (connection, NM_SETTING_VPN_SETTING_NAME))
Packit fabffb
			continue;
Packit fabffb
Packit fabffb
		if (!nm_connection_get_setting_vpn (connection)) {
Packit fabffb
			g_warning ("%s: VPN connection '%s' didn't have required vpn setting.", __func__,
Packit fabffb
			           nm_connection_get_id (connection));
Packit fabffb
			continue;
Packit fabffb
		}
Packit fabffb
Packit fabffb
		g_ptr_array_add (vpn_connections, g_object_ref (connection));
Packit fabffb
	}
Packit fabffb
Packit fabffb
	g_ptr_array_unref (all_connections);
Packit fabffb
Packit fabffb
	g_ptr_array_sort (vpn_connections, sort_vpn_connections);
Packit fabffb
	return vpn_connections;
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
nma_menu_add_vpn_submenu (GtkWidget *menu, NMApplet *applet)
Packit fabffb
{
Packit fabffb
	GtkMenu *vpn_menu;
Packit fabffb
	GtkMenuItem *item;
Packit fabffb
	GPtrArray *list;
Packit fabffb
	int i;
Packit fabffb
Packit fabffb
	vpn_menu = GTK_MENU (gtk_menu_new ());
Packit fabffb
Packit fabffb
	item = GTK_MENU_ITEM (gtk_menu_item_new_with_mnemonic (_("_VPN Connections")));
Packit fabffb
	gtk_menu_item_set_submenu (item, GTK_WIDGET (vpn_menu));
Packit fabffb
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), GTK_WIDGET (item));
Packit fabffb
	gtk_widget_show (GTK_WIDGET (item));
Packit fabffb
Packit fabffb
	list = get_vpn_connections (applet);
Packit fabffb
	for (i = 0; i < list->len; i++) {
Packit fabffb
		NMConnection *connection = NM_CONNECTION (list->pdata[i]);
Packit fabffb
		NMActiveConnection *active;
Packit fabffb
		const char *name;
Packit fabffb
		NMState state;
Packit fabffb
Packit fabffb
		name = nm_connection_get_id (connection);
Packit fabffb
Packit fabffb
		item = GTK_MENU_ITEM (gtk_check_menu_item_new_with_label (name));
Packit fabffb
Packit fabffb
		/* If no VPN connections are active, draw all menu items enabled. If
Packit fabffb
		 * >= 1 VPN connections are active, only the active VPN menu item is
Packit fabffb
		 * drawn enabled.
Packit fabffb
		 */
Packit fabffb
		active = applet_get_active_for_connection (applet, connection);
Packit fabffb
Packit fabffb
		state = nm_client_get_state (applet->nm_client);
Packit fabffb
		if (   state != NM_STATE_CONNECTED_LOCAL
Packit fabffb
		    && state != NM_STATE_CONNECTED_SITE
Packit fabffb
		    && state != NM_STATE_CONNECTED_GLOBAL)
Packit fabffb
			gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
Packit fabffb
		else
Packit fabffb
			gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE);
Packit fabffb
Packit fabffb
		gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), !!active);
Packit fabffb
Packit fabffb
		g_object_set_data_full (G_OBJECT (item), "connection",
Packit fabffb
		                        g_object_ref (connection),
Packit fabffb
		                        (GDestroyNotify) g_object_unref);
Packit fabffb
Packit fabffb
		g_signal_connect (item, "activate", G_CALLBACK (nma_menu_vpn_item_clicked), applet);
Packit fabffb
		gtk_menu_shell_append (GTK_MENU_SHELL (vpn_menu), GTK_WIDGET (item));
Packit fabffb
		gtk_widget_show (GTK_WIDGET (item));
Packit fabffb
	}
Packit fabffb
Packit fabffb
	/* Draw a separator, but only if we have VPN connections above it */
Packit fabffb
	if (list->len) {
Packit fabffb
		nma_menu_add_separator_item (GTK_WIDGET (vpn_menu));
Packit fabffb
		item = GTK_MENU_ITEM (gtk_menu_item_new_with_mnemonic (_("_Configure VPN…")));
Packit fabffb
		g_signal_connect (item, "activate", G_CALLBACK (nma_menu_configure_vpn_item_activate), applet);
Packit fabffb
	} else {
Packit fabffb
		item = GTK_MENU_ITEM (gtk_menu_item_new_with_mnemonic (_("_Add a VPN connection…")));
Packit fabffb
		g_signal_connect (item, "activate", G_CALLBACK (nma_menu_add_vpn_item_activate), applet);
Packit fabffb
	}
Packit fabffb
	gtk_menu_shell_append (GTK_MENU_SHELL (vpn_menu), GTK_WIDGET (item));
Packit fabffb
	gtk_widget_show (GTK_WIDGET (item));
Packit fabffb
Packit fabffb
	g_ptr_array_unref (list);
Packit fabffb
}
Packit fabffb
Packit fabffb
Packit fabffb
static void
Packit fabffb
nma_set_wifi_enabled_cb (GtkWidget *widget, NMApplet *applet)
Packit fabffb
{
Packit fabffb
	gboolean state;
Packit fabffb
Packit fabffb
	g_return_if_fail (applet != NULL);
Packit fabffb
Packit fabffb
	state = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget));
Packit fabffb
	nm_client_wireless_set_enabled (applet->nm_client, state);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
nma_set_wwan_enabled_cb (GtkWidget *widget, NMApplet *applet)
Packit fabffb
{
Packit fabffb
	gboolean state;
Packit fabffb
Packit fabffb
	g_return_if_fail (applet != NULL);
Packit fabffb
Packit fabffb
	state = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget));
Packit fabffb
	nm_client_wwan_set_enabled (applet->nm_client, state);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
nma_set_networking_enabled_cb (GtkWidget *widget, NMApplet *applet)
Packit fabffb
{
Packit fabffb
	gboolean state;
Packit fabffb
Packit fabffb
	g_return_if_fail (applet != NULL);
Packit fabffb
Packit fabffb
	state = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget));
Packit fabffb
	nm_client_networking_set_enabled (applet->nm_client, state, NULL);
Packit fabffb
}
Packit fabffb
Packit fabffb
Packit fabffb
static void
Packit fabffb
nma_set_notifications_enabled_cb (GtkWidget *widget, NMApplet *applet)
Packit fabffb
{
Packit fabffb
	gboolean state;
Packit fabffb
Packit fabffb
	g_return_if_fail (applet != NULL);
Packit fabffb
Packit fabffb
	state = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget));
Packit fabffb
Packit fabffb
	g_settings_set_boolean (applet->gsettings,
Packit fabffb
	                        PREF_DISABLE_CONNECTED_NOTIFICATIONS,
Packit fabffb
	                        !state);
Packit fabffb
	g_settings_set_boolean (applet->gsettings,
Packit fabffb
	                        PREF_DISABLE_DISCONNECTED_NOTIFICATIONS,
Packit fabffb
	                        !state);
Packit fabffb
	g_settings_set_boolean (applet->gsettings,
Packit fabffb
	                        PREF_DISABLE_VPN_NOTIFICATIONS,
Packit fabffb
	                        !state);
Packit fabffb
	g_settings_set_boolean (applet->gsettings,
Packit fabffb
	                        PREF_SUPPRESS_WIFI_NETWORKS_AVAILABLE,
Packit fabffb
	                        !state);
Packit fabffb
}
Packit fabffb
Packit fabffb
static gboolean
Packit fabffb
has_usable_wifi (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	const GPtrArray *devices;
Packit fabffb
	int i;
Packit fabffb
Packit fabffb
	if (!nm_client_wireless_get_enabled (applet->nm_client))
Packit fabffb
		return FALSE;
Packit fabffb
Packit fabffb
	devices = nm_client_get_devices (applet->nm_client);
Packit fabffb
	if (!devices)
Packit fabffb
		return FALSE;
Packit fabffb
Packit fabffb
	for (i = 0; i < devices->len; i++) {
Packit fabffb
		NMDevice *device = devices->pdata[i];
Packit fabffb
Packit fabffb
		if (   NM_IS_DEVICE_WIFI (device)
Packit fabffb
		    && (nm_device_get_state (device) >= NM_DEVICE_STATE_DISCONNECTED))
Packit fabffb
			return TRUE;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	return FALSE;
Packit fabffb
}
Packit fabffb
Packit fabffb
/*
Packit fabffb
 * nma_menu_show_cb
Packit fabffb
 *
Packit fabffb
 * Pop up the wifi networks menu
Packit fabffb
 *
Packit fabffb
 */
Packit fabffb
static void nma_menu_show_cb (GtkWidget *menu, NMApplet *applet)
Packit fabffb
{
Packit fabffb
	g_return_if_fail (menu != NULL);
Packit fabffb
	g_return_if_fail (applet != NULL);
Packit fabffb
Packit fabffb
	if (applet->status_icon)
Packit fabffb
		gtk_status_icon_set_tooltip_text (applet->status_icon, NULL);
Packit fabffb
Packit fabffb
	if (!nm_client_get_nm_running (applet->nm_client)) {
Packit fabffb
		nma_menu_add_text_item (menu, _("NetworkManager is not running…"));
Packit fabffb
		return;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	if (nm_client_get_state (applet->nm_client) == NM_STATE_ASLEEP) {
Packit fabffb
		nma_menu_add_text_item (menu, _("Networking disabled"));
Packit fabffb
		return;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	nma_menu_add_devices (menu, applet);
Packit fabffb
Packit fabffb
	if (has_usable_wifi (applet)) {
Packit fabffb
		/* Add the "Hidden Wi-Fi network..." entry */
Packit fabffb
		nma_menu_add_hidden_network_item (menu, applet);
Packit fabffb
		nma_menu_add_create_network_item (menu, applet);
Packit fabffb
		nma_menu_add_separator_item (menu);
Packit fabffb
	}
Packit fabffb
	nma_menu_add_vpn_submenu (menu, applet);
Packit fabffb
Packit fabffb
	if (!INDICATOR_ENABLED (applet))
Packit fabffb
		gtk_widget_show_all (menu);
Packit fabffb
}
Packit fabffb
Packit fabffb
static gboolean
Packit fabffb
destroy_old_menu (gpointer user_data)
Packit fabffb
{
Packit fabffb
	g_object_unref (user_data);
Packit fabffb
	return FALSE;
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
nma_menu_deactivate_cb (GtkWidget *widget, NMApplet *applet)
Packit fabffb
{
Packit fabffb
	/* Must punt the destroy to a low-priority idle to ensure that
Packit fabffb
	 * the menu items don't get destroyed before any 'activate' signal
Packit fabffb
	 * fires for an item.
Packit fabffb
	 */
Packit fabffb
	g_signal_handlers_disconnect_by_func (applet->menu, G_CALLBACK (nma_menu_deactivate_cb), applet);
Packit fabffb
	g_idle_add_full (G_PRIORITY_LOW, destroy_old_menu, applet->menu, NULL);
Packit fabffb
	applet->menu = NULL;
Packit fabffb
Packit fabffb
	applet_stop_wifi_scan (applet, NULL);
Packit fabffb
Packit fabffb
	/* Re-set the tooltip */
Packit fabffb
	gtk_status_icon_set_tooltip_text (applet->status_icon, applet->tip);
Packit fabffb
}
Packit fabffb
Packit fabffb
static gboolean
Packit fabffb
is_permission_yes (NMApplet *applet, NMClientPermission perm)
Packit fabffb
{
Packit fabffb
	if (   applet->permissions[perm] == NM_CLIENT_PERMISSION_RESULT_YES
Packit fabffb
	    || applet->permissions[perm] == NM_CLIENT_PERMISSION_RESULT_AUTH)
Packit fabffb
		return TRUE;
Packit fabffb
	return FALSE;
Packit fabffb
}
Packit fabffb
Packit fabffb
/*
Packit fabffb
 * nma_context_menu_update
Packit fabffb
 *
Packit fabffb
 */
Packit fabffb
static void
Packit fabffb
nma_context_menu_update (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	NMState state;
Packit fabffb
	gboolean net_enabled = TRUE;
Packit fabffb
	gboolean have_wifi = FALSE;
Packit fabffb
	gboolean have_wwan = FALSE;
Packit fabffb
	gboolean wifi_hw_enabled;
Packit fabffb
	gboolean wwan_hw_enabled;
Packit fabffb
	gboolean notifications_enabled = TRUE;
Packit fabffb
	gboolean sensitive = FALSE;
Packit fabffb
Packit fabffb
	state = nm_client_get_state (applet->nm_client);
Packit fabffb
	sensitive = (   state == NM_STATE_CONNECTED_LOCAL
Packit fabffb
	             || state == NM_STATE_CONNECTED_SITE
Packit fabffb
	             || state == NM_STATE_CONNECTED_GLOBAL);
Packit fabffb
	gtk_widget_set_sensitive (applet->info_menu_item, sensitive);
Packit fabffb
Packit fabffb
	/* Update checkboxes, and block 'toggled' signal when updating so that the
Packit fabffb
	 * callback doesn't get triggered.
Packit fabffb
	 */
Packit fabffb
Packit fabffb
	/* Enabled Networking */
Packit fabffb
	g_signal_handler_block (G_OBJECT (applet->networking_enabled_item),
Packit fabffb
	                        applet->networking_enabled_toggled_id);
Packit fabffb
	net_enabled = nm_client_networking_get_enabled (applet->nm_client);
Packit fabffb
	gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (applet->networking_enabled_item),
Packit fabffb
	                                net_enabled && (state != NM_STATE_ASLEEP));
Packit fabffb
	g_signal_handler_unblock (G_OBJECT (applet->networking_enabled_item),
Packit fabffb
	                          applet->networking_enabled_toggled_id);
Packit fabffb
	gtk_widget_set_sensitive (applet->networking_enabled_item,
Packit fabffb
	                          is_permission_yes (applet, NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK));
Packit fabffb
Packit fabffb
	/* Enabled Wi-Fi */
Packit fabffb
	g_signal_handler_block (G_OBJECT (applet->wifi_enabled_item),
Packit fabffb
	                        applet->wifi_enabled_toggled_id);
Packit fabffb
	gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (applet->wifi_enabled_item),
Packit fabffb
	                                nm_client_wireless_get_enabled (applet->nm_client));
Packit fabffb
	g_signal_handler_unblock (G_OBJECT (applet->wifi_enabled_item),
Packit fabffb
	                          applet->wifi_enabled_toggled_id);
Packit fabffb
Packit fabffb
	wifi_hw_enabled = nm_client_wireless_hardware_get_enabled (applet->nm_client);
Packit fabffb
	gtk_widget_set_sensitive (GTK_WIDGET (applet->wifi_enabled_item),
Packit fabffb
	                          wifi_hw_enabled && is_permission_yes (applet, NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI));
Packit fabffb
Packit fabffb
	/* Enabled Mobile Broadband */
Packit fabffb
	g_signal_handler_block (G_OBJECT (applet->wwan_enabled_item),
Packit fabffb
	                        applet->wwan_enabled_toggled_id);
Packit fabffb
	gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (applet->wwan_enabled_item),
Packit fabffb
	                                nm_client_wwan_get_enabled (applet->nm_client));
Packit fabffb
	g_signal_handler_unblock (G_OBJECT (applet->wwan_enabled_item),
Packit fabffb
	                          applet->wwan_enabled_toggled_id);
Packit fabffb
Packit fabffb
	wwan_hw_enabled = nm_client_wwan_hardware_get_enabled (applet->nm_client);
Packit fabffb
	gtk_widget_set_sensitive (GTK_WIDGET (applet->wwan_enabled_item),
Packit fabffb
	                          wwan_hw_enabled && is_permission_yes (applet, NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN));
Packit fabffb
Packit fabffb
	if (!INDICATOR_ENABLED (applet)) {
Packit fabffb
		/* Enabled notifications */
Packit fabffb
		g_signal_handler_block (G_OBJECT (applet->notifications_enabled_item),
Packit fabffb
			                    applet->notifications_enabled_toggled_id);
Packit fabffb
		if (   g_settings_get_boolean (applet->gsettings, PREF_DISABLE_CONNECTED_NOTIFICATIONS)
Packit fabffb
			&& g_settings_get_boolean (applet->gsettings, PREF_DISABLE_DISCONNECTED_NOTIFICATIONS)
Packit fabffb
			&& g_settings_get_boolean (applet->gsettings, PREF_DISABLE_VPN_NOTIFICATIONS)
Packit fabffb
			&& g_settings_get_boolean (applet->gsettings, PREF_SUPPRESS_WIFI_NETWORKS_AVAILABLE))
Packit fabffb
			notifications_enabled = FALSE;
Packit fabffb
		gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (applet->notifications_enabled_item), notifications_enabled);
Packit fabffb
		g_signal_handler_unblock (G_OBJECT (applet->notifications_enabled_item),
Packit fabffb
			                      applet->notifications_enabled_toggled_id);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	/* Don't show wifi-specific stuff if wifi is off */
Packit fabffb
	if (state != NM_STATE_ASLEEP) {
Packit fabffb
		const GPtrArray *devices;
Packit fabffb
		int i;
Packit fabffb
Packit fabffb
		devices = nm_client_get_devices (applet->nm_client);
Packit fabffb
		for (i = 0; devices && (i < devices->len); i++) {
Packit fabffb
			NMDevice *candidate = g_ptr_array_index (devices, i);
Packit fabffb
Packit fabffb
			if (NM_IS_DEVICE_WIFI (candidate))
Packit fabffb
				have_wifi = TRUE;
Packit fabffb
			else if (NM_IS_DEVICE_MODEM (candidate))
Packit fabffb
				have_wwan = TRUE;
Packit fabffb
		}
Packit fabffb
	}
Packit fabffb
Packit fabffb
	if (have_wifi)
Packit fabffb
		gtk_widget_show_all (applet->wifi_enabled_item);
Packit fabffb
	else
Packit fabffb
		gtk_widget_hide (applet->wifi_enabled_item);
Packit fabffb
Packit fabffb
	if (have_wwan)
Packit fabffb
		gtk_widget_show_all (applet->wwan_enabled_item);
Packit fabffb
	else
Packit fabffb
		gtk_widget_hide (applet->wwan_enabled_item);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
ce_child_setup (gpointer user_data G_GNUC_UNUSED)
Packit fabffb
{
Packit fabffb
	/* We are in the child process at this point */
Packit fabffb
	pid_t pid = getpid ();
Packit fabffb
	setpgid (pid, pid);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
nma_edit_connections_cb (void)
Packit fabffb
{
Packit fabffb
	char *argv[2];
Packit fabffb
	GError *error = NULL;
Packit fabffb
	gboolean success;
Packit fabffb
Packit fabffb
	argv[0] = BINDIR "/nm-connection-editor";
Packit fabffb
	argv[1] = NULL;
Packit fabffb
Packit fabffb
	success = g_spawn_async ("/", argv, NULL, 0, &ce_child_setup, NULL, NULL, &error);
Packit fabffb
	if (!success) {
Packit fabffb
		g_warning ("Error launching connection editor: %s", error->message);
Packit fabffb
		g_error_free (error);
Packit fabffb
	}
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_connection_info_cb (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	applet_info_dialog_show (applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
/*
Packit fabffb
 * nma_context_menu_populate
Packit fabffb
 *
Packit fabffb
 * Populate the contextual popup menu.
Packit fabffb
 *
Packit fabffb
 */
Packit fabffb
static void nma_context_menu_populate (NMApplet *applet, GtkMenu *menu)
Packit fabffb
{
Packit fabffb
	GtkMenuShell *menu_shell;
Packit fabffb
	guint id;
Packit fabffb
	static gboolean icons_shown = FALSE;
Packit fabffb
Packit fabffb
	g_return_if_fail (applet != NULL);
Packit fabffb
Packit fabffb
	menu_shell = GTK_MENU_SHELL (menu);
Packit fabffb
Packit fabffb
	if (G_UNLIKELY (icons_shown == FALSE)) {
Packit fabffb
		GtkSettings *settings = gtk_widget_get_settings (GTK_WIDGET (menu_shell));
Packit fabffb
Packit fabffb
		/* We always want our icons displayed */
Packit fabffb
		if (settings)
Packit fabffb
			g_object_set (G_OBJECT (settings), "gtk-menu-images", TRUE, NULL);
Packit fabffb
		icons_shown = TRUE;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	/* 'Enable Networking' item */
Packit fabffb
	applet->networking_enabled_item = gtk_check_menu_item_new_with_mnemonic (_("Enable _Networking"));
Packit fabffb
	id = g_signal_connect (applet->networking_enabled_item,
Packit fabffb
	                       "toggled",
Packit fabffb
	                       G_CALLBACK (nma_set_networking_enabled_cb),
Packit fabffb
	                       applet);
Packit fabffb
	applet->networking_enabled_toggled_id = id;
Packit fabffb
	gtk_menu_shell_append (menu_shell, applet->networking_enabled_item);
Packit fabffb
Packit fabffb
	/* 'Enable Wi-Fi' item */
Packit fabffb
	applet->wifi_enabled_item = gtk_check_menu_item_new_with_mnemonic (_("Enable _Wi-Fi"));
Packit fabffb
	id = g_signal_connect (applet->wifi_enabled_item,
Packit fabffb
	                       "toggled",
Packit fabffb
	                       G_CALLBACK (nma_set_wifi_enabled_cb),
Packit fabffb
	                       applet);
Packit fabffb
	applet->wifi_enabled_toggled_id = id;
Packit fabffb
	gtk_menu_shell_append (menu_shell, applet->wifi_enabled_item);
Packit fabffb
Packit fabffb
	/* 'Enable Mobile Broadband' item */
Packit fabffb
	applet->wwan_enabled_item = gtk_check_menu_item_new_with_mnemonic (_("Enable _Mobile Broadband"));
Packit fabffb
	id = g_signal_connect (applet->wwan_enabled_item,
Packit fabffb
	                       "toggled",
Packit fabffb
	                       G_CALLBACK (nma_set_wwan_enabled_cb),
Packit fabffb
	                       applet);
Packit fabffb
	applet->wwan_enabled_toggled_id = id;
Packit fabffb
	gtk_menu_shell_append (menu_shell, applet->wwan_enabled_item);
Packit fabffb
Packit fabffb
	nma_menu_add_separator_item (GTK_WIDGET (menu_shell));
Packit fabffb
Packit fabffb
	if (!INDICATOR_ENABLED (applet)) {
Packit fabffb
		/* Toggle notifications item */
Packit fabffb
		applet->notifications_enabled_item = gtk_check_menu_item_new_with_mnemonic (_("Enable N_otifications"));
Packit fabffb
		id = g_signal_connect (applet->notifications_enabled_item,
Packit fabffb
			                   "toggled",
Packit fabffb
			                   G_CALLBACK (nma_set_notifications_enabled_cb),
Packit fabffb
			                   applet);
Packit fabffb
		applet->notifications_enabled_toggled_id = id;
Packit fabffb
		gtk_menu_shell_append (menu_shell, applet->notifications_enabled_item);
Packit fabffb
Packit fabffb
		nma_menu_add_separator_item (GTK_WIDGET (menu_shell));
Packit fabffb
	}
Packit fabffb
Packit fabffb
	/* 'Connection Information' item */
Packit fabffb
	applet->info_menu_item = gtk_menu_item_new_with_mnemonic (_("Connection _Information"));
Packit fabffb
	g_signal_connect_swapped (applet->info_menu_item,
Packit fabffb
	                          "activate",
Packit fabffb
	                          G_CALLBACK (applet_connection_info_cb),
Packit fabffb
	                          applet);
Packit fabffb
	gtk_menu_shell_append (menu_shell, applet->info_menu_item);
Packit fabffb
Packit fabffb
	/* 'Edit Connections...' item */
Packit fabffb
	applet->connections_menu_item = gtk_menu_item_new_with_mnemonic (_("Edit Connections…"));
Packit fabffb
	g_signal_connect (applet->connections_menu_item,
Packit fabffb
				   "activate",
Packit fabffb
				   G_CALLBACK (nma_edit_connections_cb),
Packit fabffb
				   applet);
Packit fabffb
	gtk_menu_shell_append (menu_shell, applet->connections_menu_item);
Packit fabffb
Packit fabffb
	/* Separator */
Packit fabffb
	nma_menu_add_separator_item (GTK_WIDGET (menu_shell));
Packit fabffb
Packit fabffb
	if (!INDICATOR_ENABLED (applet)) {
Packit fabffb
		/* About item */
Packit fabffb
		GtkWidget *menu_item;
Packit fabffb
Packit fabffb
		menu_item = gtk_menu_item_new_with_mnemonic (_("_About"));
Packit fabffb
		g_signal_connect_swapped (menu_item, "activate", G_CALLBACK (applet_about_dialog_show), applet);
Packit fabffb
		gtk_menu_shell_append (menu_shell, menu_item);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	gtk_widget_show_all (GTK_WIDGET (menu_shell));
Packit fabffb
}
Packit fabffb
Packit fabffb
typedef struct {
Packit fabffb
	NMApplet *applet;
Packit fabffb
	NMDevice *device;
Packit fabffb
	NMConnection *connection;
Packit fabffb
} AppletMenuItemInfo;
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_menu_item_info_destroy (gpointer data, GClosure *closure)
Packit fabffb
{
Packit fabffb
	AppletMenuItemInfo *info = data;
Packit fabffb
Packit fabffb
	g_clear_object (&info->device);
Packit fabffb
	g_clear_object (&info->connection);
Packit fabffb
Packit fabffb
	g_slice_free (AppletMenuItemInfo, data);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_menu_item_activate (GtkMenuItem *item, gpointer user_data)
Packit fabffb
{
Packit fabffb
	AppletMenuItemInfo *info = user_data;
Packit fabffb
Packit fabffb
	applet_menu_item_activate_helper (info->device,
Packit fabffb
	                                  info->connection,
Packit fabffb
	                                  "/",
Packit fabffb
	                                  info->applet,
Packit fabffb
	                                  user_data);
Packit fabffb
}
Packit fabffb
Packit fabffb
void
Packit fabffb
applet_add_connection_items (NMDevice *device,
Packit fabffb
                             const GPtrArray *connections,
Packit fabffb
                             gboolean sensitive,
Packit fabffb
                             NMConnection *active,
Packit fabffb
                             NMAAddActiveInactiveEnum flag,
Packit fabffb
                             GtkWidget *menu,
Packit fabffb
                             NMApplet *applet)
Packit fabffb
{
Packit fabffb
	int i;
Packit fabffb
	AppletMenuItemInfo *info;
Packit fabffb
Packit fabffb
	for (i = 0; i < connections->len; i++) {
Packit fabffb
		NMConnection *connection = NM_CONNECTION (connections->pdata[i]);
Packit fabffb
		GtkWidget *item;
Packit fabffb
Packit fabffb
		if (active == connection) {
Packit fabffb
			if ((flag & NMA_ADD_ACTIVE) == 0)
Packit fabffb
				continue;
Packit fabffb
		} else {
Packit fabffb
			if ((flag & NMA_ADD_INACTIVE) == 0)
Packit fabffb
				continue;
Packit fabffb
		}
Packit fabffb
Packit fabffb
		item = applet_new_menu_item_helper (connection, active, (flag & NMA_ADD_ACTIVE));
Packit fabffb
		gtk_widget_set_sensitive (item, sensitive);
Packit fabffb
		gtk_widget_show_all (item);
Packit fabffb
Packit fabffb
		info = g_slice_new0 (AppletMenuItemInfo);
Packit fabffb
		info->applet = applet;
Packit fabffb
		info->device = device ? g_object_ref (device) : NULL;
Packit fabffb
		info->connection = g_object_ref (connection);
Packit fabffb
Packit fabffb
		g_signal_connect_data (item, "activate",
Packit fabffb
		                       G_CALLBACK (applet_menu_item_activate),
Packit fabffb
		                       info,
Packit fabffb
		                       applet_menu_item_info_destroy, 0);
Packit fabffb
Packit fabffb
		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
Packit fabffb
	}
Packit fabffb
}
Packit fabffb
Packit fabffb
void
Packit fabffb
applet_add_default_connection_item (NMDevice *device,
Packit fabffb
                                    const char *label,
Packit fabffb
                                    gboolean sensitive,
Packit fabffb
                                    GtkWidget *menu,
Packit fabffb
                                    NMApplet *applet)
Packit fabffb
{
Packit fabffb
	AppletMenuItemInfo *info;
Packit fabffb
	GtkWidget *item;
Packit fabffb
Packit fabffb
	item = gtk_check_menu_item_new_with_label (label);
Packit fabffb
	gtk_widget_set_sensitive (GTK_WIDGET (item), sensitive);
Packit fabffb
	gtk_check_menu_item_set_draw_as_radio (GTK_CHECK_MENU_ITEM (item), TRUE);
Packit fabffb
Packit fabffb
	info = g_slice_new0 (AppletMenuItemInfo);
Packit fabffb
	info->applet = applet;
Packit fabffb
	info->device = g_object_ref (device);
Packit fabffb
Packit fabffb
	g_signal_connect_data (item, "activate",
Packit fabffb
	                       G_CALLBACK (applet_menu_item_activate),
Packit fabffb
	                       info,
Packit fabffb
	                       applet_menu_item_info_destroy, 0);
Packit fabffb
Packit fabffb
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
Packit fabffb
}
Packit fabffb
Packit fabffb
static gboolean
Packit fabffb
applet_update_menu (gpointer user_data)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (user_data);
Packit fabffb
	GList *children, *elt;
Packit fabffb
	GtkMenu *menu;
Packit fabffb
Packit fabffb
	if (INDICATOR_ENABLED (applet)) {
Packit fabffb
#ifdef WITH_APPINDICATOR
Packit fabffb
		menu = app_indicator_get_menu (applet->app_indicator);
Packit fabffb
		if (!menu) {
Packit fabffb
			menu = GTK_MENU (gtk_menu_new ());
Packit fabffb
			app_indicator_set_menu (applet->app_indicator, menu);
Packit fabffb
			g_signal_connect_swapped (menu, "show", G_CALLBACK (applet_start_wifi_scan), applet);
Packit fabffb
			g_signal_connect_swapped (menu, "hide", G_CALLBACK (applet_stop_wifi_scan), applet);
Packit fabffb
		}
Packit fabffb
#else
Packit fabffb
		g_return_val_if_reached (G_SOURCE_REMOVE);
Packit fabffb
#endif /* WITH_APPINDICATOR */
Packit fabffb
	} else {
Packit fabffb
		menu = GTK_MENU (applet->menu);
Packit fabffb
		if (!menu) {
Packit fabffb
			/* Menu not open */
Packit fabffb
			goto out;
Packit fabffb
		}
Packit fabffb
	}
Packit fabffb
Packit fabffb
	/* Clear all entries */
Packit fabffb
	children = gtk_container_get_children (GTK_CONTAINER (menu));
Packit fabffb
	for (elt = children; elt; elt = g_list_next (elt))
Packit fabffb
		gtk_container_remove (GTK_CONTAINER (menu), GTK_WIDGET (elt->data));
Packit fabffb
	g_list_free (children);
Packit fabffb
Packit fabffb
	/* Update the menu */
Packit fabffb
	if (INDICATOR_ENABLED (applet)) {
Packit fabffb
		nma_menu_show_cb (GTK_WIDGET (menu), applet);
Packit fabffb
		nma_menu_add_separator_item (GTK_WIDGET (menu));
Packit fabffb
		nma_context_menu_populate (applet, menu);
Packit fabffb
		nma_context_menu_update (applet);
Packit fabffb
	} else
Packit fabffb
		nma_menu_show_cb (GTK_WIDGET (menu), applet);
Packit fabffb
Packit fabffb
out:
Packit fabffb
	applet->update_menu_id = 0;
Packit fabffb
	return G_SOURCE_REMOVE;
Packit fabffb
}
Packit fabffb
Packit fabffb
void
Packit fabffb
applet_schedule_update_menu (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	if (!applet->update_menu_id)
Packit fabffb
		applet->update_menu_id = g_idle_add (applet_update_menu, applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
static void
Packit fabffb
foo_set_icon (NMApplet *applet, guint32 layer, GdkPixbuf *pixbuf, const char *icon_name)
Packit fabffb
{
Packit fabffb
	gs_unref_object GdkPixbuf *pixbuf_free = NULL;
Packit fabffb
Packit fabffb
	g_return_if_fail (layer == ICON_LAYER_LINK || layer == ICON_LAYER_VPN);
Packit fabffb
Packit fabffb
#ifdef WITH_APPINDICATOR
Packit fabffb
	if (INDICATOR_ENABLED (applet)) {
Packit fabffb
		/* FIXME: We rely on the fact that VPN icon gets drawn later and therefore
Packit fabffb
		 * wins but we cannot currently set a combined pixmap made of both the link
Packit fabffb
		 * icon and the VPN icon.
Packit fabffb
		 */
Packit fabffb
		if (icon_name == NULL && layer == ICON_LAYER_LINK)
Packit fabffb
			icon_name = "nm-no-connection";
Packit fabffb
		if (icon_name != NULL && g_strcmp0 (app_indicator_get_icon (applet->app_indicator), icon_name) != 0)
Packit fabffb
			app_indicator_set_icon_full (applet->app_indicator, icon_name, applet->tip);
Packit fabffb
		return;
Packit fabffb
	}
Packit fabffb
#endif  /* WITH_APPINDICATOR */
Packit fabffb
Packit fabffb
	/* Load the pixbuf by icon name */
Packit fabffb
	if (icon_name && !pixbuf)
Packit fabffb
		pixbuf = nma_icon_check_and_load (icon_name, applet);
Packit fabffb
Packit fabffb
	/* Ignore setting of the same icon as is already displayed */
Packit fabffb
	if (applet->icon_layers[layer] == pixbuf)
Packit fabffb
		return;
Packit fabffb
Packit fabffb
	g_clear_object (&applet->icon_layers[layer]);
Packit fabffb
Packit fabffb
	if (pixbuf)
Packit fabffb
		applet->icon_layers[layer] = g_object_ref (pixbuf);
Packit fabffb
Packit fabffb
	if (applet->icon_layers[0]) {
Packit fabffb
		int i;
Packit fabffb
Packit fabffb
		pixbuf = applet->icon_layers[0];
Packit fabffb
Packit fabffb
		for (i = ICON_LAYER_LINK + 1; i <= ICON_LAYER_MAX; i++) {
Packit fabffb
			GdkPixbuf *top = applet->icon_layers[i];
Packit fabffb
Packit fabffb
			if (!top)
Packit fabffb
				continue;
Packit fabffb
Packit fabffb
			if (!pixbuf_free)
Packit fabffb
				pixbuf = pixbuf_free = gdk_pixbuf_copy (pixbuf);
Packit fabffb
Packit fabffb
			gdk_pixbuf_composite (top, pixbuf, 0, 0, gdk_pixbuf_get_width (top),
Packit fabffb
			                      gdk_pixbuf_get_height (top),
Packit fabffb
			                      0, 0, 1.0, 1.0,
Packit fabffb
			                      GDK_INTERP_NEAREST, 255);
Packit fabffb
		}
Packit fabffb
	} else
Packit fabffb
		pixbuf = nma_icon_check_and_load ("nm-no-connection", applet);
Packit fabffb
Packit fabffb
	gtk_status_icon_set_from_pixbuf (applet->status_icon, pixbuf);
Packit fabffb
}
Packit fabffb
Packit fabffb
NMRemoteConnection *
Packit fabffb
applet_get_exported_connection_for_device (NMDevice *device, NMApplet *applet)
Packit fabffb
{
Packit fabffb
	const GPtrArray *active_connections;
Packit fabffb
	int i;
Packit fabffb
Packit fabffb
	active_connections = nm_client_get_active_connections (applet->nm_client);
Packit fabffb
	for (i = 0; active_connections && (i < active_connections->len); i++) {
Packit fabffb
		NMActiveConnection *active;
Packit fabffb
		NMRemoteConnection *connection;
Packit fabffb
		const GPtrArray *devices;
Packit fabffb
Packit fabffb
		active = g_ptr_array_index (active_connections, i);
Packit fabffb
		if (!active)
Packit fabffb
			continue;
Packit fabffb
Packit fabffb
		devices = nm_active_connection_get_devices (active);
Packit fabffb
		connection = nm_active_connection_get_connection (active);
Packit fabffb
		if (!devices || !connection)
Packit fabffb
			continue;
Packit fabffb
Packit fabffb
		if (!nm_g_ptr_array_contains (devices, device))
Packit fabffb
			continue;
Packit fabffb
Packit fabffb
		return connection;
Packit fabffb
	}
Packit fabffb
	return NULL;
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_common_device_state_changed (NMDevice *device,
Packit fabffb
                                    NMDeviceState new_state,
Packit fabffb
                                    NMDeviceState old_state,
Packit fabffb
                                    NMDeviceStateReason reason,
Packit fabffb
                                    NMApplet *applet)
Packit fabffb
{
Packit fabffb
	gboolean device_activating = FALSE, vpn_activating = FALSE;
Packit fabffb
Packit fabffb
	device_activating = applet_is_any_device_activating (applet);
Packit fabffb
	vpn_activating = applet_is_any_vpn_activating (applet);
Packit fabffb
Packit fabffb
Packit fabffb
	switch (new_state) {
Packit fabffb
	case NM_DEVICE_STATE_PREPARE:
Packit fabffb
	case NM_DEVICE_STATE_CONFIG:
Packit fabffb
	case NM_DEVICE_STATE_NEED_AUTH:
Packit fabffb
	case NM_DEVICE_STATE_IP_CONFIG:
Packit fabffb
		/* Be sure to turn animation timeout on here since the dbus signals
Packit fabffb
		 * for new active connections or devices might not have come through yet.
Packit fabffb
		 */
Packit fabffb
		device_activating = TRUE;
Packit fabffb
		break;
Packit fabffb
	case NM_DEVICE_STATE_ACTIVATED:
Packit fabffb
	default:
Packit fabffb
		break;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	/* If there's an activating device but we're not animating, start animation.
Packit fabffb
	 * If we're animating, but there's no activating device or VPN, stop animating.
Packit fabffb
	 */
Packit fabffb
	if (device_activating || vpn_activating)
Packit fabffb
		start_animation_timeout (applet);
Packit fabffb
	else
Packit fabffb
		clear_animation_timeout (applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
foo_device_state_changed_cb (NMDevice *device,
Packit fabffb
                             NMDeviceState new_state,
Packit fabffb
                             NMDeviceState old_state,
Packit fabffb
                             NMDeviceStateReason reason,
Packit fabffb
                             gpointer user_data)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (user_data);
Packit fabffb
	NMADeviceClass *dclass;
Packit fabffb
Packit fabffb
	dclass = get_device_class (device, applet);
Packit fabffb
Packit fabffb
	if (dclass && dclass->device_state_changed)
Packit fabffb
		dclass->device_state_changed (device, new_state, old_state, reason, applet);
Packit fabffb
Packit fabffb
	applet_common_device_state_changed (device, new_state, old_state, reason, applet);
Packit fabffb
Packit fabffb
	if (   dclass
Packit fabffb
	    && new_state == NM_DEVICE_STATE_ACTIVATED
Packit fabffb
	    && !g_settings_get_boolean (applet->gsettings, PREF_DISABLE_CONNECTED_NOTIFICATIONS)) {
Packit fabffb
		NMConnection *connection;
Packit fabffb
		char *str = NULL;
Packit fabffb
Packit fabffb
		connection = applet_find_active_connection_for_device (device, applet, NULL);
Packit fabffb
		if (connection) {
Packit fabffb
			str = g_strdup_printf (_("You are now connected to “%s”."),
Packit fabffb
			                       nm_connection_get_id (connection));
Packit fabffb
		}
Packit fabffb
Packit fabffb
		dclass->notify_connected (device, str, applet);
Packit fabffb
		g_free (str);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	applet_schedule_update_icon (applet);
Packit fabffb
	applet_schedule_update_menu (applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
foo_device_added_cb (NMClient *client, NMDevice *device, gpointer user_data)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (user_data);
Packit fabffb
	NMADeviceClass *dclass;
Packit fabffb
Packit fabffb
	dclass = get_device_class (device, applet);
Packit fabffb
	if (dclass && dclass->device_added)
Packit fabffb
		dclass->device_added (device, applet);
Packit fabffb
Packit fabffb
	g_signal_connect (device, "state-changed",
Packit fabffb
	                  G_CALLBACK (foo_device_state_changed_cb),
Packit fabffb
	                  user_data);
Packit fabffb
Packit fabffb
	foo_device_state_changed_cb	(device,
Packit fabffb
	                             nm_device_get_state (device),
Packit fabffb
	                             NM_DEVICE_STATE_UNKNOWN,
Packit fabffb
	                             NM_DEVICE_STATE_REASON_NONE,
Packit fabffb
	                             applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
foo_client_state_changed_cb (NMClient *client, GParamSpec *pspec, gpointer user_data)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (user_data);
Packit fabffb
Packit fabffb
	switch (nm_client_get_state (client)) {
Packit fabffb
	case NM_STATE_DISCONNECTED:
Packit fabffb
		applet_do_notify_with_pref (applet, _("Disconnected"),
Packit fabffb
		                            _("The network connection has been disconnected."),
Packit fabffb
		                            "nm-no-connection",
Packit fabffb
		                            PREF_DISABLE_DISCONNECTED_NOTIFICATIONS);
Packit fabffb
		break;
Packit fabffb
	default:
Packit fabffb
		break;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	applet_schedule_update_icon (applet);
Packit fabffb
	applet_schedule_update_menu (applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
foo_device_removed_cb (NMClient *client, NMDevice *device, NMApplet *applet)
Packit fabffb
{
Packit fabffb
	applet_schedule_update_icon (applet);
Packit fabffb
	applet_schedule_update_menu (applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
foo_manager_running_cb (NMClient *client,
Packit fabffb
                        GParamSpec *pspec,
Packit fabffb
                        gpointer user_data)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (user_data);
Packit fabffb
Packit fabffb
	if (nm_client_get_nm_running (client)) {
Packit fabffb
		g_debug ("NM appeared");
Packit fabffb
	} else {
Packit fabffb
		g_debug ("NM disappeared");
Packit fabffb
		clear_animation_timeout (applet);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	applet_schedule_update_icon (applet);
Packit fabffb
	applet_schedule_update_menu (applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
vpn_state_changed (NMActiveConnection *connection,
Packit fabffb
                   GParamSpec *pspec,
Packit fabffb
                   gpointer user_data)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (user_data);
Packit fabffb
Packit fabffb
	applet_schedule_update_icon (applet);
Packit fabffb
	applet_schedule_update_menu (applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
#define VPN_STATE_ID_TAG "vpn-state-id"
Packit fabffb
Packit fabffb
static void
Packit fabffb
foo_active_connections_changed_cb (NMClient *client,
Packit fabffb
                                   GParamSpec *pspec,
Packit fabffb
                                   gpointer user_data)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (user_data);
Packit fabffb
	const GPtrArray *active_list;
Packit fabffb
	int i;
Packit fabffb
Packit fabffb
	/* Track the state of new VPN connections */
Packit fabffb
	active_list = nm_client_get_active_connections (client);
Packit fabffb
	for (i = 0; active_list && (i < active_list->len); i++) {
Packit fabffb
		NMActiveConnection *candidate = NM_ACTIVE_CONNECTION (g_ptr_array_index (active_list, i));
Packit fabffb
		guint id;
Packit fabffb
Packit fabffb
		if (   !NM_IS_VPN_CONNECTION (candidate)
Packit fabffb
		    || g_object_get_data (G_OBJECT (candidate), VPN_STATE_ID_TAG))
Packit fabffb
			continue;
Packit fabffb
Packit fabffb
		/* Start/stop animation when the AC state changes ... */
Packit fabffb
		id = g_signal_connect (G_OBJECT (candidate), "state-changed",
Packit fabffb
		                       G_CALLBACK (vpn_active_connection_state_changed), applet);
Packit fabffb
		/* ... and also update icon/tooltip when the VPN state changes */
Packit fabffb
		g_signal_connect (G_OBJECT (candidate), "notify::vpn-state",
Packit fabffb
		                  G_CALLBACK (vpn_state_changed), applet);
Packit fabffb
Packit fabffb
		g_object_set_data (G_OBJECT (candidate), VPN_STATE_ID_TAG, GUINT_TO_POINTER (id));
Packit fabffb
	}
Packit fabffb
Packit fabffb
	applet_schedule_update_icon (applet);
Packit fabffb
	applet_schedule_update_menu (applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
foo_manager_permission_changed (NMClient *client,
Packit fabffb
                                NMClientPermission permission,
Packit fabffb
                                NMClientPermissionResult result,
Packit fabffb
                                gpointer user_data)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (user_data);
Packit fabffb
Packit fabffb
	if (permission <= NM_CLIENT_PERMISSION_LAST)
Packit fabffb
		applet->permissions[permission] = result;
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
foo_wireless_enabled_changed_cb (NMClient *client, GParamSpec *pspec, NMApplet *applet)
Packit fabffb
{
Packit fabffb
	applet_schedule_update_icon (applet);
Packit fabffb
	applet_schedule_update_menu (applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
static gboolean
Packit fabffb
foo_set_initial_state (gpointer data)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (data);
Packit fabffb
	const GPtrArray *devices;
Packit fabffb
	int i;
Packit fabffb
Packit fabffb
	devices = nm_client_get_devices (applet->nm_client);
Packit fabffb
	for (i = 0; devices && (i < devices->len); i++)
Packit fabffb
		foo_device_added_cb (applet->nm_client, NM_DEVICE (g_ptr_array_index (devices, i)), applet);
Packit fabffb
Packit fabffb
	foo_active_connections_changed_cb (applet->nm_client, NULL, applet);
Packit fabffb
Packit fabffb
	applet_schedule_update_icon (applet);
Packit fabffb
Packit fabffb
	return FALSE;
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
foo_client_setup (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	NMClientPermission perm;
Packit fabffb
Packit fabffb
	applet->nm_client = nm_client_new (NULL, NULL);
Packit fabffb
	if (!applet->nm_client)
Packit fabffb
		return;
Packit fabffb
Packit fabffb
	g_signal_connect (applet->nm_client, "notify::state",
Packit fabffb
	                  G_CALLBACK (foo_client_state_changed_cb),
Packit fabffb
	                  applet);
Packit fabffb
	g_signal_connect (applet->nm_client, "notify::active-connections",
Packit fabffb
	                  G_CALLBACK (foo_active_connections_changed_cb),
Packit fabffb
	                  applet);
Packit fabffb
	g_signal_connect (applet->nm_client, "device-added",
Packit fabffb
	                  G_CALLBACK (foo_device_added_cb),
Packit fabffb
	                  applet);
Packit fabffb
	if (INDICATOR_ENABLED (applet)) {
Packit fabffb
		g_signal_connect (applet->nm_client, "device-removed",
Packit fabffb
		                  G_CALLBACK (foo_device_removed_cb),
Packit fabffb
		                  applet);
Packit fabffb
	}
Packit fabffb
	g_signal_connect (applet->nm_client, "notify::manager-running",
Packit fabffb
	                  G_CALLBACK (foo_manager_running_cb),
Packit fabffb
	                  applet);
Packit fabffb
Packit fabffb
	g_signal_connect (applet->nm_client, "permission-changed",
Packit fabffb
	                  G_CALLBACK (foo_manager_permission_changed),
Packit fabffb
	                  applet);
Packit fabffb
Packit fabffb
	g_signal_connect (applet->nm_client, "notify::wireless-enabled",
Packit fabffb
	                  G_CALLBACK (foo_wireless_enabled_changed_cb),
Packit fabffb
	                  applet);
Packit fabffb
Packit fabffb
	g_signal_connect (applet->nm_client, "notify::wwan-enabled",
Packit fabffb
	                  G_CALLBACK (foo_wireless_enabled_changed_cb),
Packit fabffb
	                  applet);
Packit fabffb
Packit fabffb
	/* Initialize permissions - the initial 'permission-changed' signal is emitted from NMClient constructor, and thus not caught */
Packit fabffb
	for (perm = NM_CLIENT_PERMISSION_NONE + 1; perm <= NM_CLIENT_PERMISSION_LAST; perm++) {
Packit fabffb
		applet->permissions[perm] = nm_client_get_permission_result (applet->nm_client, perm);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	if (nm_client_get_nm_running (applet->nm_client))
Packit fabffb
		g_idle_add (foo_set_initial_state, applet);
Packit fabffb
Packit fabffb
	applet_schedule_update_icon (applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
#if WITH_WWAN
Packit fabffb
Packit fabffb
static void
Packit fabffb
mm1_name_owner_changed_cb (GDBusObjectManagerClient *mm1,
Packit fabffb
                           GParamSpec *pspec,
Packit fabffb
                           NMApplet *applet)
Packit fabffb
{
Packit fabffb
	gchar *name_owner;
Packit fabffb
Packit fabffb
	name_owner = g_dbus_object_manager_client_get_name_owner (mm1);
Packit fabffb
	applet->mm1_running = !!name_owner;
Packit fabffb
	g_free (name_owner);
Packit fabffb
Packit fabffb
	if (applet->mm1_running) {
Packit fabffb
		const GPtrArray *devices;
Packit fabffb
		NMADeviceClass *dclass;
Packit fabffb
		NMDevice *device;
Packit fabffb
		int i;
Packit fabffb
Packit fabffb
		devices = nm_client_get_devices (applet->nm_client);
Packit fabffb
		for (i = 0; devices && (i < devices->len); i++) {
Packit fabffb
			device = NM_DEVICE (g_ptr_array_index (devices, i));
Packit fabffb
			if (NM_IS_DEVICE_MODEM (device)) {
Packit fabffb
				dclass = get_device_class (device, applet);
Packit fabffb
				if (dclass && dclass->device_added)
Packit fabffb
					dclass->device_added (device, applet);
Packit fabffb
Packit fabffb
				applet_schedule_update_icon (applet);
Packit fabffb
				applet_schedule_update_menu (applet);
Packit fabffb
			}
Packit fabffb
		}
Packit fabffb
	}
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
mm_new_ready (GDBusConnection *connection,
Packit fabffb
              GAsyncResult *res,
Packit fabffb
              NMApplet *applet)
Packit fabffb
{
Packit fabffb
	GError *error = NULL;
Packit fabffb
Packit fabffb
	applet->mm1 = mm_manager_new_finish (res, &error);
Packit fabffb
	if (applet->mm1) {
Packit fabffb
		/* We've got our MM proxy, now check whether the ModemManager
Packit fabffb
		 * is really running and usable */
Packit fabffb
		g_signal_connect (applet->mm1,
Packit fabffb
		                  "notify::name-owner",
Packit fabffb
		                  G_CALLBACK (mm1_name_owner_changed_cb),
Packit fabffb
		                  applet);
Packit fabffb
		mm1_name_owner_changed_cb (G_DBUS_OBJECT_MANAGER_CLIENT (applet->mm1), NULL, applet);
Packit fabffb
	} else {
Packit fabffb
		g_warning ("Error connecting to D-Bus: %s", error->message);
Packit fabffb
		g_clear_error (&error);
Packit fabffb
	}
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
mm1_client_setup (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	GDBusConnection *system_bus;
Packit fabffb
	GError *error = NULL;
Packit fabffb
Packit fabffb
	system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
Packit fabffb
	if (system_bus) {
Packit fabffb
		mm_manager_new (system_bus,
Packit fabffb
		                G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START,
Packit fabffb
		                NULL,
Packit fabffb
		                (GAsyncReadyCallback) mm_new_ready,
Packit fabffb
		                applet);
Packit fabffb
		g_object_unref (system_bus);
Packit fabffb
	} else {
Packit fabffb
		g_warning ("Error connecting to system D-Bus: %s", error->message);
Packit fabffb
		g_clear_error (&error);
Packit fabffb
	}
Packit fabffb
}
Packit fabffb
Packit fabffb
#endif /* WITH_WWAN */
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_common_get_device_icon (NMDeviceState state,
Packit fabffb
                               GdkPixbuf **out_pixbuf,
Packit fabffb
                               char **out_icon_name,
Packit fabffb
                               NMApplet *applet)
Packit fabffb
{
Packit fabffb
	int stage = -1;
Packit fabffb
Packit fabffb
	switch (state) {
Packit fabffb
	case NM_DEVICE_STATE_PREPARE:
Packit fabffb
		stage = 0;
Packit fabffb
		break;
Packit fabffb
	case NM_DEVICE_STATE_CONFIG:
Packit fabffb
	case NM_DEVICE_STATE_NEED_AUTH:
Packit fabffb
		stage = 1;
Packit fabffb
		break;
Packit fabffb
	case NM_DEVICE_STATE_IP_CONFIG:
Packit fabffb
		stage = 2;
Packit fabffb
		break;
Packit fabffb
	default:
Packit fabffb
		break;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	if (stage >= 0) {
Packit fabffb
		char *name = g_strdup_printf ("nm-stage%02d-connecting%02d", stage + 1, applet->animation_step + 1);
Packit fabffb
Packit fabffb
		if (out_pixbuf)
Packit fabffb
			*out_pixbuf = nm_g_object_ref (nma_icon_check_and_load (name, applet));
Packit fabffb
		if (out_icon_name)
Packit fabffb
			*out_icon_name = name;
Packit fabffb
		else
Packit fabffb
			g_free (name);
Packit fabffb
Packit fabffb
		applet->animation_step++;
Packit fabffb
		if (applet->animation_step >= NUM_CONNECTING_FRAMES)
Packit fabffb
			applet->animation_step = 0;
Packit fabffb
	}
Packit fabffb
}
Packit fabffb
Packit fabffb
static char *
Packit fabffb
get_tip_for_device_state (NMDevice *device,
Packit fabffb
                          NMDeviceState state,
Packit fabffb
                          NMConnection *connection)
Packit fabffb
{
Packit fabffb
	char *tip = NULL;
Packit fabffb
	const char *id = NULL;
Packit fabffb
Packit fabffb
	id = nm_device_get_iface (device);
Packit fabffb
	if (connection)
Packit fabffb
		id = nm_connection_get_id (connection);
Packit fabffb
Packit fabffb
	switch (state) {
Packit fabffb
	case NM_DEVICE_STATE_PREPARE:
Packit fabffb
	case NM_DEVICE_STATE_CONFIG:
Packit fabffb
		tip = g_strdup_printf (_("Preparing network connection “%s”…"), id);
Packit fabffb
		break;
Packit fabffb
	case NM_DEVICE_STATE_NEED_AUTH:
Packit fabffb
		tip = g_strdup_printf (_("User authentication required for network connection “%s”…"), id);
Packit fabffb
		break;
Packit fabffb
	case NM_DEVICE_STATE_IP_CONFIG:
Packit fabffb
		tip = g_strdup_printf (_("Requesting a network address for “%s”…"), id);
Packit fabffb
		break;
Packit fabffb
	case NM_DEVICE_STATE_ACTIVATED:
Packit fabffb
		tip = g_strdup_printf (_("Network connection “%s” active"), id);
Packit fabffb
		break;
Packit fabffb
	default:
Packit fabffb
		break;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	return tip;
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_get_device_icon_for_state (NMApplet *applet,
Packit fabffb
                                  GdkPixbuf **out_pixbuf,
Packit fabffb
                                  char **out_icon_name,
Packit fabffb
                                  char **out_tip)
Packit fabffb
{
Packit fabffb
	NMActiveConnection *active;
Packit fabffb
	NMDevice *device = NULL;
Packit fabffb
	NMDeviceState state = NM_DEVICE_STATE_UNKNOWN;
Packit fabffb
	NMADeviceClass *dclass;
Packit fabffb
Packit fabffb
	g_assert (out_pixbuf && out_icon_name && out_tip);
Packit fabffb
	g_assert (!*out_pixbuf && !*out_icon_name && !*out_tip);
Packit fabffb
Packit fabffb
	// FIXME: handle multiple device states here
Packit fabffb
Packit fabffb
	/* First show the best activating device's state */
Packit fabffb
	active = applet_get_best_activating_connection (applet, &device);
Packit fabffb
	if (!active || !device) {
Packit fabffb
		/* If there aren't any activating devices, then show the state of
Packit fabffb
		 * the default active connection instead.
Packit fabffb
		 */
Packit fabffb
		active = applet_get_default_active_connection (applet, &device, TRUE);
Packit fabffb
		if (!active || !device)
Packit fabffb
			goto out;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	state = nm_device_get_state (device);
Packit fabffb
Packit fabffb
	dclass = get_device_class (device, applet);
Packit fabffb
	if (dclass) {
Packit fabffb
		NMConnection *connection;
Packit fabffb
		const char *icon_name = NULL;
Packit fabffb
Packit fabffb
		connection = applet_find_active_connection_for_device (device, applet, NULL);
Packit fabffb
Packit fabffb
		dclass->get_icon (device, state, connection, out_pixbuf, &icon_name, out_tip, applet);
Packit fabffb
Packit fabffb
		if (!*out_pixbuf && icon_name)
Packit fabffb
			*out_pixbuf = nm_g_object_ref (nma_icon_check_and_load (icon_name, applet));
Packit fabffb
		*out_icon_name = g_strdup (icon_name);
Packit fabffb
		if (!*out_tip)
Packit fabffb
			*out_tip = get_tip_for_device_state (device, state, connection);
Packit fabffb
		if (icon_name || *out_pixbuf)
Packit fabffb
			return;
Packit fabffb
	}
Packit fabffb
Packit fabffb
out:
Packit fabffb
	applet_common_get_device_icon (state, out_pixbuf, out_icon_name, applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
static char *
Packit fabffb
get_tip_for_vpn (NMActiveConnection *active, NMVpnConnectionState state, NMApplet *applet)
Packit fabffb
{
Packit fabffb
	char *tip = NULL;
Packit fabffb
	const char *id = NULL;
Packit fabffb
Packit fabffb
	id = nm_active_connection_get_id (active);
Packit fabffb
	if (!id)
Packit fabffb
		return NULL;
Packit fabffb
Packit fabffb
	switch (state) {
Packit fabffb
	case NM_VPN_CONNECTION_STATE_CONNECT:
Packit fabffb
	case NM_VPN_CONNECTION_STATE_PREPARE:
Packit fabffb
		tip = g_strdup_printf (_("Starting VPN connection “%s”…"), id);
Packit fabffb
		break;
Packit fabffb
	case NM_VPN_CONNECTION_STATE_NEED_AUTH:
Packit fabffb
		tip = g_strdup_printf (_("User authentication required for VPN connection “%s”…"), id);
Packit fabffb
		break;
Packit fabffb
	case NM_VPN_CONNECTION_STATE_IP_CONFIG_GET:
Packit fabffb
		tip = g_strdup_printf (_("Requesting a VPN address for “%s”…"), id);
Packit fabffb
		break;
Packit fabffb
	case NM_VPN_CONNECTION_STATE_ACTIVATED:
Packit fabffb
		tip = g_strdup_printf (_("VPN connection active"));
Packit fabffb
		break;
Packit fabffb
	default:
Packit fabffb
		break;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	return tip;
Packit fabffb
}
Packit fabffb
Packit fabffb
static gboolean
Packit fabffb
applet_update_icon (gpointer user_data)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (user_data);
Packit fabffb
	gs_unref_object GdkPixbuf *pixbuf = NULL;
Packit fabffb
	NMState state;
Packit fabffb
	const char *icon_name, *dev_tip;
Packit fabffb
	char *vpn_tip = NULL;
Packit fabffb
	gs_free char *icon_name_free = NULL;
Packit fabffb
	gs_free char *dev_tip_free = NULL;
Packit fabffb
	NMVpnConnectionState vpn_state = NM_VPN_CONNECTION_STATE_UNKNOWN;
Packit fabffb
	gboolean nm_running;
Packit fabffb
	NMActiveConnection *active_vpn = NULL;
Packit fabffb
Packit fabffb
	applet->update_icon_id = 0;
Packit fabffb
Packit fabffb
	nm_running = nm_client_get_nm_running (applet->nm_client);
Packit fabffb
Packit fabffb
	/* Handle device state first */
Packit fabffb
Packit fabffb
	state = nm_client_get_state (applet->nm_client);
Packit fabffb
	if (!nm_running)
Packit fabffb
		state = NM_STATE_UNKNOWN;
Packit fabffb
Packit fabffb
#ifdef WITH_APPINDICATOR
Packit fabffb
	if (INDICATOR_ENABLED (applet))
Packit fabffb
		app_indicator_set_status (applet->app_indicator, nm_running ? APP_INDICATOR_STATUS_ACTIVE : APP_INDICATOR_STATUS_PASSIVE);
Packit fabffb
	else
Packit fabffb
#endif  /* WITH_APPINDICATOR */
Packit fabffb
	{
Packit fabffb
		gtk_status_icon_set_visible (applet->status_icon, applet->visible);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	switch (state) {
Packit fabffb
	case NM_STATE_UNKNOWN:
Packit fabffb
	case NM_STATE_ASLEEP:
Packit fabffb
		icon_name = "nm-no-connection";
Packit fabffb
		dev_tip = _("Networking disabled");
Packit fabffb
		break;
Packit fabffb
	case NM_STATE_DISCONNECTED:
Packit fabffb
		icon_name = "nm-no-connection";
Packit fabffb
		dev_tip = _("No network connection");
Packit fabffb
		break;
Packit fabffb
	default:
Packit fabffb
		applet_get_device_icon_for_state (applet, &pixbuf, &icon_name_free, &dev_tip_free);
Packit fabffb
		icon_name = icon_name_free;
Packit fabffb
		dev_tip = dev_tip_free;
Packit fabffb
		break;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	foo_set_icon (applet, ICON_LAYER_LINK, pixbuf, icon_name);
Packit fabffb
Packit fabffb
	icon_name = NULL;
Packit fabffb
	g_clear_pointer (&icon_name_free, g_free);
Packit fabffb
Packit fabffb
	/* VPN state next */
Packit fabffb
	active_vpn = applet_get_active_vpn_connection (applet, &vpn_state);
Packit fabffb
	if (active_vpn) {
Packit fabffb
		switch (vpn_state) {
Packit fabffb
		case NM_VPN_CONNECTION_STATE_ACTIVATED:
Packit fabffb
			icon_name = "nm-vpn-active-lock";
Packit fabffb
#ifdef WITH_APPINDICATOR
Packit fabffb
			if (INDICATOR_ENABLED (applet))
Packit fabffb
				icon_name = icon_name_free = g_strdup_printf ("%s-secure", app_indicator_get_icon (applet->app_indicator));
Packit fabffb
#endif /* WITH_APPINDICATOR */
Packit fabffb
			break;
Packit fabffb
		case NM_VPN_CONNECTION_STATE_PREPARE:
Packit fabffb
		case NM_VPN_CONNECTION_STATE_NEED_AUTH:
Packit fabffb
		case NM_VPN_CONNECTION_STATE_CONNECT:
Packit fabffb
		case NM_VPN_CONNECTION_STATE_IP_CONFIG_GET:
Packit fabffb
			icon_name = icon_name_free = g_strdup_printf ("nm-vpn-connecting%02d", applet->animation_step + 1);
Packit fabffb
			applet->animation_step++;
Packit fabffb
			if (applet->animation_step >= NUM_VPN_CONNECTING_FRAMES)
Packit fabffb
				applet->animation_step = 0;
Packit fabffb
			break;
Packit fabffb
		default:
Packit fabffb
			break;
Packit fabffb
		}
Packit fabffb
Packit fabffb
		vpn_tip = get_tip_for_vpn (active_vpn, vpn_state, applet);
Packit fabffb
		if (vpn_tip && dev_tip) {
Packit fabffb
			char *tmp;
Packit fabffb
Packit fabffb
			tmp = g_strdup_printf ("%s\n%s", dev_tip, vpn_tip);
Packit fabffb
			g_free (vpn_tip);
Packit fabffb
			vpn_tip = tmp;
Packit fabffb
		}
Packit fabffb
	}
Packit fabffb
	foo_set_icon (applet, ICON_LAYER_VPN, NULL, icon_name);
Packit fabffb
Packit fabffb
	/* update tooltip */
Packit fabffb
	g_free (applet->tip);
Packit fabffb
	if (vpn_tip)
Packit fabffb
		applet->tip = vpn_tip;
Packit fabffb
	else if (dev_tip == dev_tip_free) {
Packit fabffb
		applet->tip = dev_tip_free;
Packit fabffb
		dev_tip_free = NULL;
Packit fabffb
	} else
Packit fabffb
		applet->tip = g_strdup (dev_tip);
Packit fabffb
Packit fabffb
	if (applet->status_icon)
Packit fabffb
		gtk_status_icon_set_tooltip_text (applet->status_icon, applet->tip);
Packit fabffb
Packit fabffb
	return FALSE;
Packit fabffb
}
Packit fabffb
Packit fabffb
void
Packit fabffb
applet_schedule_update_icon (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	if (!applet->update_icon_id)
Packit fabffb
		applet->update_icon_id = g_idle_add (applet_update_icon, applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
static SecretsRequest *
Packit fabffb
applet_secrets_request_new (size_t totsize,
Packit fabffb
                            NMConnection *connection,
Packit fabffb
                            gpointer request_id,
Packit fabffb
                            const char *setting_name,
Packit fabffb
                            const char **hints,
Packit fabffb
                            guint32 flags,
Packit fabffb
                            AppletAgentSecretsCallback callback,
Packit fabffb
                            gpointer callback_data,
Packit fabffb
                            NMApplet *applet)
Packit fabffb
{
Packit fabffb
	SecretsRequest *req;
Packit fabffb
Packit fabffb
	g_return_val_if_fail (totsize >= sizeof (SecretsRequest), NULL);
Packit fabffb
	g_return_val_if_fail (connection != NULL, NULL);
Packit fabffb
Packit fabffb
	req = g_malloc0 (totsize);
Packit fabffb
	req->totsize = totsize;
Packit fabffb
	req->connection = g_object_ref (connection);
Packit fabffb
	req->reqid = request_id;
Packit fabffb
	req->setting_name = g_strdup (setting_name);
Packit fabffb
	req->hints = g_strdupv ((char **) hints);
Packit fabffb
	req->flags = flags;
Packit fabffb
	req->callback = callback;
Packit fabffb
	req->callback_data = callback_data;
Packit fabffb
	req->applet = applet;
Packit fabffb
	return req;
Packit fabffb
}
Packit fabffb
Packit fabffb
void
Packit fabffb
applet_secrets_request_set_free_func (SecretsRequest *req,
Packit fabffb
                                      SecretsRequestFreeFunc free_func)
Packit fabffb
{
Packit fabffb
	req->free_func = free_func;
Packit fabffb
}
Packit fabffb
Packit fabffb
void
Packit fabffb
applet_secrets_request_complete (SecretsRequest *req,
Packit fabffb
                                 GVariant *settings,
Packit fabffb
                                 GError *error)
Packit fabffb
{
Packit fabffb
	req->callback (req->applet->agent, error ? NULL : settings, error, req->callback_data);
Packit fabffb
}
Packit fabffb
Packit fabffb
void
Packit fabffb
applet_secrets_request_complete_setting (SecretsRequest *req,
Packit fabffb
                                         const char *setting_name,
Packit fabffb
                                         GError *error)
Packit fabffb
{
Packit fabffb
	NMSetting *setting;
Packit fabffb
	GVariant *secrets_dict = NULL;
Packit fabffb
Packit fabffb
	if (setting_name && !error) {
Packit fabffb
		setting = nm_connection_get_setting_by_name (req->connection, setting_name);
Packit fabffb
		if (setting) {
Packit fabffb
			secrets_dict = nm_connection_to_dbus (req->connection, NM_CONNECTION_SERIALIZE_ALL);
Packit fabffb
			if (!secrets_dict) {
Packit fabffb
				g_set_error (&error,
Packit fabffb
				             NM_SECRET_AGENT_ERROR,
Packit fabffb
				             NM_SECRET_AGENT_ERROR_FAILED,
Packit fabffb
				             "%s.%d (%s): failed to hash setting '%s'.",
Packit fabffb
				             __FILE__, __LINE__, __func__, setting_name);
Packit fabffb
			}
Packit fabffb
		} else {
Packit fabffb
			g_set_error (&error,
Packit fabffb
			             NM_SECRET_AGENT_ERROR,
Packit fabffb
			             NM_SECRET_AGENT_ERROR_FAILED,
Packit fabffb
			             "%s.%d (%s): unhandled setting '%s'",
Packit fabffb
			             __FILE__, __LINE__, __func__, setting_name);
Packit fabffb
		}
Packit fabffb
	}
Packit fabffb
Packit fabffb
	req->callback (req->applet->agent, secrets_dict, error, req->callback_data);
Packit fabffb
}
Packit fabffb
Packit fabffb
void
Packit fabffb
applet_secrets_request_free (SecretsRequest *req)
Packit fabffb
{
Packit fabffb
	g_return_if_fail (req != NULL);
Packit fabffb
Packit fabffb
	if (req->free_func)
Packit fabffb
		req->free_func (req);
Packit fabffb
Packit fabffb
	req->applet->secrets_reqs = g_slist_remove (req->applet->secrets_reqs, req);
Packit fabffb
Packit fabffb
	g_object_unref (req->connection);
Packit fabffb
	g_free (req->setting_name);
Packit fabffb
	g_strfreev (req->hints);
Packit fabffb
	memset (req, 0, req->totsize);
Packit fabffb
	g_free (req);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
get_existing_secrets_cb (NMSecretAgentOld *agent,
Packit fabffb
                         NMConnection *connection,
Packit fabffb
                         GVariant *secrets,
Packit fabffb
                         GError *secrets_error,
Packit fabffb
                         gpointer user_data)
Packit fabffb
{
Packit fabffb
	SecretsRequest *req = user_data;
Packit fabffb
	NMADeviceClass *dclass;
Packit fabffb
	GError *error = NULL;
Packit fabffb
Packit fabffb
	if (secrets)
Packit fabffb
		nm_connection_update_secrets (connection, req->setting_name, secrets, NULL);
Packit fabffb
	else
Packit fabffb
		nm_connection_clear_secrets (connection);
Packit fabffb
Packit fabffb
	dclass = get_device_class_from_connection (connection, req->applet);
Packit fabffb
	g_assert (dclass);
Packit fabffb
Packit fabffb
	/* Let the device class handle secrets */
Packit fabffb
	if (!dclass->get_secrets (req, &error)) {
Packit fabffb
		g_warning ("%s:%d - %s", __func__, __LINE__, error ? error->message : "(unknown)");
Packit fabffb
		applet_secrets_request_complete (req, NULL, error);
Packit fabffb
		applet_secrets_request_free (req);
Packit fabffb
		g_error_free (error);
Packit fabffb
	}
Packit fabffb
	/* Otherwise success; wait for the secrets callback */
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_agent_get_secrets_cb (AppletAgent *agent,
Packit fabffb
                             gpointer request_id,
Packit fabffb
                             NMConnection *connection,
Packit fabffb
                             const char *setting_name,
Packit fabffb
                             const char **hints,
Packit fabffb
                             guint32 flags,
Packit fabffb
                             AppletAgentSecretsCallback callback,
Packit fabffb
                             gpointer callback_data,
Packit fabffb
                             gpointer user_data)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (user_data);
Packit fabffb
	NMSettingConnection *s_con;
Packit fabffb
	NMADeviceClass *dclass;
Packit fabffb
	GError *error = NULL;
Packit fabffb
	SecretsRequest *req = NULL;
Packit fabffb
Packit fabffb
	s_con = nm_connection_get_setting_connection (connection);
Packit fabffb
	g_return_if_fail (s_con != NULL);
Packit fabffb
Packit fabffb
	/* VPN secrets get handled a bit differently */
Packit fabffb
	if (!strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_VPN_SETTING_NAME)) {
Packit fabffb
		req = applet_secrets_request_new (applet_vpn_request_get_secrets_size (),
Packit fabffb
		                                  connection,
Packit fabffb
		                                  request_id,
Packit fabffb
		                                  setting_name,
Packit fabffb
		                                  hints,
Packit fabffb
		                                  flags,
Packit fabffb
		                                  callback,
Packit fabffb
		                                  callback_data,
Packit fabffb
		                                  applet);
Packit fabffb
		if (!applet_vpn_request_get_secrets (req, &error))
Packit fabffb
			goto error;
Packit fabffb
Packit fabffb
		applet->secrets_reqs = g_slist_prepend (applet->secrets_reqs, req);
Packit fabffb
		return;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	dclass = get_device_class_from_connection (connection, applet);
Packit fabffb
	if (!dclass) {
Packit fabffb
		error = g_error_new (NM_SECRET_AGENT_ERROR,
Packit fabffb
		                     NM_SECRET_AGENT_ERROR_FAILED,
Packit fabffb
		                     "%s.%d (%s): device type unknown",
Packit fabffb
		                     __FILE__, __LINE__, __func__);
Packit fabffb
		goto error;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	if (!dclass->get_secrets) {
Packit fabffb
		error = g_error_new (NM_SECRET_AGENT_ERROR,
Packit fabffb
		                     NM_SECRET_AGENT_ERROR_NO_SECRETS,
Packit fabffb
		                     "%s.%d (%s): no secrets found",
Packit fabffb
		                     __FILE__, __LINE__, __func__);
Packit fabffb
		goto error;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	g_assert (dclass->secrets_request_size);
Packit fabffb
	req = applet_secrets_request_new (dclass->secrets_request_size,
Packit fabffb
	                                  connection,
Packit fabffb
	                                  request_id,
Packit fabffb
	                                  setting_name,
Packit fabffb
	                                  hints,
Packit fabffb
	                                  flags,
Packit fabffb
	                                  callback,
Packit fabffb
	                                  callback_data,
Packit fabffb
	                                  applet);
Packit fabffb
	applet->secrets_reqs = g_slist_prepend (applet->secrets_reqs, req);
Packit fabffb
Packit fabffb
	/* Get existing secrets, if any */
Packit fabffb
	nm_secret_agent_old_get_secrets (NM_SECRET_AGENT_OLD (applet->agent),
Packit fabffb
	                                 connection,
Packit fabffb
	                                 setting_name,
Packit fabffb
	                                 hints,
Packit fabffb
	                                 NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE,
Packit fabffb
	                                 get_existing_secrets_cb,
Packit fabffb
	                                 req);
Packit fabffb
	return;
Packit fabffb
Packit fabffb
error:
Packit fabffb
	g_warning ("%s", error->message);
Packit fabffb
	callback (agent, NULL, error, callback_data);
Packit fabffb
	g_error_free (error);
Packit fabffb
Packit fabffb
	if (req)
Packit fabffb
		applet_secrets_request_free (req);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_agent_cancel_secrets_cb (AppletAgent *agent,
Packit fabffb
                                gpointer request_id,
Packit fabffb
                                gpointer user_data)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (user_data);
Packit fabffb
	GSList *iter, *next;
Packit fabffb
Packit fabffb
	for (iter = applet->secrets_reqs; iter; iter = next) {
Packit fabffb
		SecretsRequest *req = iter->data;
Packit fabffb
Packit fabffb
		next = g_slist_next (iter);
Packit fabffb
Packit fabffb
		if (req->reqid == request_id) {
Packit fabffb
			/* cancel and free this password request */
Packit fabffb
			applet_secrets_request_free (req);
Packit fabffb
			break;
Packit fabffb
		}
Packit fabffb
	}
Packit fabffb
}
Packit fabffb
Packit fabffb
/*****************************************************************************/
Packit fabffb
Packit fabffb
static void nma_icons_free (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	guint i;
Packit fabffb
Packit fabffb
	g_return_if_fail (NM_IS_APPLET (applet));
Packit fabffb
Packit fabffb
	for (i = 0; i <= ICON_LAYER_MAX; i++)
Packit fabffb
		g_clear_object (&applet->icon_layers[i]);
Packit fabffb
}
Packit fabffb
Packit fabffb
GdkPixbuf *
Packit fabffb
nma_icon_check_and_load (const char *name, NMApplet *applet)
Packit fabffb
{
Packit fabffb
	GError *error = NULL;
Packit fabffb
	GdkPixbuf *icon;
Packit Service 639700
	int scale;
Packit fabffb
Packit fabffb
	g_assert (name != NULL);
Packit fabffb
	g_assert (applet != NULL);
Packit fabffb
Packit fabffb
	/* icon already loaded successfully */
Packit fabffb
	if (g_hash_table_lookup_extended (applet->icon_cache, name, NULL, (gpointer) &icon))
Packit fabffb
		return icon;
Packit fabffb
Packit Service 639700
	scale = gdk_window_get_scale_factor (gdk_get_default_root_window ());
Packit Service 639700
Packit fabffb
	/* Try to load the icon; if the load fails, log the problem, and set
Packit fabffb
	 * the icon to the fallback icon if requested.
Packit fabffb
	 */
Packit Service 639700
	if (!(icon = gtk_icon_theme_load_icon_for_scale (applet->icon_theme, name, applet->icon_size, scale, GTK_ICON_LOOKUP_FORCE_SIZE, &error))) {
Packit fabffb
		g_warning ("failed to load icon \"%s\": %s", name, error->message);
Packit fabffb
		g_clear_error (&error);
Packit fabffb
		icon = nm_g_object_ref (applet->fallback_icon);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	g_hash_table_insert (applet->icon_cache, g_strdup (name), icon);
Packit fabffb
Packit fabffb
	return icon;
Packit fabffb
}
Packit fabffb
Packit fabffb
#include "fallback-icon.h"
Packit fabffb
Packit fabffb
static void
Packit fabffb
nma_icons_reload (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	GError *error = NULL;
Packit fabffb
	gs_unref_object GdkPixbufLoader *loader = NULL;
Packit fabffb
Packit fabffb
	g_return_if_fail (applet->icon_size > 0);
Packit fabffb
Packit fabffb
	g_hash_table_remove_all (applet->icon_cache);
Packit fabffb
	nma_icons_free (applet);
Packit fabffb
Packit fabffb
	if (applet->fallback_icon)
Packit fabffb
		return;
Packit fabffb
Packit fabffb
	loader = gdk_pixbuf_loader_new_with_type ("png", &error);
Packit fabffb
	if (!loader)
Packit fabffb
		goto error;
Packit fabffb
Packit fabffb
	if (!gdk_pixbuf_loader_write (loader,
Packit fabffb
	                              fallback_icon_data,
Packit fabffb
	                              sizeof (fallback_icon_data),
Packit fabffb
	                              &error))
Packit fabffb
		goto error;
Packit fabffb
Packit fabffb
	if (!gdk_pixbuf_loader_close (loader, &error))
Packit fabffb
		goto error;
Packit fabffb
Packit fabffb
	applet->fallback_icon = nm_g_object_ref (gdk_pixbuf_loader_get_pixbuf (loader));
Packit fabffb
	g_warn_if_fail (applet->fallback_icon);
Packit fabffb
	return;
Packit fabffb
Packit fabffb
error:
Packit fabffb
	g_warning ("failed loading default-icon: %s", error->message);
Packit fabffb
	g_clear_error (&error);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void nma_icon_theme_changed (GtkIconTheme *icon_theme, NMApplet *applet)
Packit fabffb
{
Packit fabffb
	nma_icons_reload (applet);
Packit fabffb
	applet_schedule_update_icon (applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void nma_icons_init (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	gboolean path_appended;
Packit fabffb
Packit fabffb
	if (applet->icon_theme) {
Packit fabffb
		g_signal_handlers_disconnect_by_func (applet->icon_theme,
Packit fabffb
		                                      G_CALLBACK (nma_icon_theme_changed),
Packit fabffb
		                                      applet);
Packit fabffb
		g_object_unref (G_OBJECT (applet->icon_theme));
Packit fabffb
	}
Packit fabffb
Packit fabffb
	if (applet->status_icon)
Packit fabffb
		applet->icon_theme = gtk_icon_theme_get_for_screen (gtk_status_icon_get_screen (applet->status_icon));
Packit fabffb
	else
Packit fabffb
		applet->icon_theme = gtk_icon_theme_get_default ();
Packit fabffb
Packit fabffb
	/* If not done yet, append our search path */
Packit fabffb
	path_appended = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (applet->icon_theme),
Packit fabffb
	                                 "NMAIconPathAppended"));
Packit fabffb
	if (path_appended == FALSE) {
Packit fabffb
		gtk_icon_theme_append_search_path (applet->icon_theme, ICONDIR);
Packit fabffb
		g_object_set_data (G_OBJECT (applet->icon_theme),
Packit fabffb
		                   "NMAIconPathAppended",
Packit fabffb
		                   GINT_TO_POINTER (TRUE));
Packit fabffb
	}
Packit fabffb
Packit fabffb
	g_signal_connect (applet->icon_theme, "changed", G_CALLBACK (nma_icon_theme_changed), applet);
Packit fabffb
Packit fabffb
	nma_icons_reload (applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
status_icon_screen_changed_cb (GtkStatusIcon *icon,
Packit fabffb
                               GParamSpec *pspec,
Packit fabffb
                               NMApplet *applet)
Packit fabffb
{
Packit fabffb
	nma_icons_init (applet);
Packit fabffb
}
Packit fabffb
Packit fabffb
static gboolean
Packit fabffb
status_icon_size_changed_cb (GtkStatusIcon *icon,
Packit fabffb
                             gint size,
Packit fabffb
                             NMApplet *applet)
Packit fabffb
{
Packit fabffb
	g_debug ("%s(): status icon size %d requested", __func__, size);
Packit fabffb
Packit fabffb
	/* icon_size may be 0 if for example the panel hasn't given us any space
Packit fabffb
	 * yet.  We'll get resized later, but for now just load the 16x16 icons.
Packit fabffb
	 */
Packit fabffb
	if (size > 0)
Packit fabffb
		applet->icon_size = size;
Packit fabffb
	else {
Packit fabffb
		applet->icon_size = 16;
Packit fabffb
		g_warn_if_fail (size == 0);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	nma_icons_reload (applet);
Packit fabffb
Packit fabffb
	applet_schedule_update_icon (applet);
Packit fabffb
Packit fabffb
	return TRUE;
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
status_icon_activate_cb (GtkStatusIcon *icon, NMApplet *applet)
Packit fabffb
{
Packit fabffb
	/* Have clicking on the applet act also as acknowledgement
Packit fabffb
	 * of the notification.
Packit fabffb
	 */
Packit fabffb
	applet_clear_notify (applet);
Packit fabffb
Packit fabffb
	applet_start_wifi_scan (applet, NULL);
Packit fabffb
Packit fabffb
	/* Kill any old menu */
Packit fabffb
	if (applet->menu)
Packit fabffb
		g_object_unref (applet->menu);
Packit fabffb
Packit fabffb
	/* And make a fresh new one */
Packit fabffb
	applet->menu = gtk_menu_new ();
Packit fabffb
	/* Sink the ref so we can explicitly destroy the menu later */
Packit fabffb
	g_object_ref_sink (G_OBJECT (applet->menu));
Packit fabffb
Packit fabffb
	gtk_container_set_border_width (GTK_CONTAINER (applet->menu), 0);
Packit fabffb
	g_signal_connect (applet->menu, "show", G_CALLBACK (nma_menu_show_cb), applet);
Packit fabffb
	g_signal_connect (applet->menu, "deactivate", G_CALLBACK (nma_menu_deactivate_cb), applet);
Packit fabffb
Packit fabffb
	/* Display the new menu */
Packit fabffb
	gtk_menu_popup (GTK_MENU (applet->menu), NULL, NULL,
Packit fabffb
	                gtk_status_icon_position_menu, icon,
Packit fabffb
	                1, gtk_get_current_event_time ());
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
status_icon_popup_menu_cb (GtkStatusIcon *icon,
Packit fabffb
                           guint button,
Packit fabffb
                           guint32 activate_time,
Packit fabffb
                           NMApplet *applet)
Packit fabffb
{
Packit fabffb
	/* Have clicking on the applet act also as acknowledgement
Packit fabffb
	 * of the notification.
Packit fabffb
	 */
Packit fabffb
	applet_clear_notify (applet);
Packit fabffb
Packit fabffb
	nma_context_menu_update (applet);
Packit fabffb
	gtk_menu_popup (GTK_MENU (applet->context_menu), NULL, NULL,
Packit fabffb
			gtk_status_icon_position_menu, icon,
Packit fabffb
			button, activate_time);
Packit fabffb
}
Packit fabffb
Packit fabffb
static gboolean
Packit fabffb
setup_widgets (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	GtkMenu *menu;
Packit fabffb
Packit fabffb
#ifdef WITH_APPINDICATOR
Packit fabffb
	if (with_appindicator) {
Packit fabffb
		applet->app_indicator = app_indicator_new ("nm-applet",
Packit fabffb
		                                           "nm-no-connection",
Packit fabffb
		                                           APP_INDICATOR_CATEGORY_SYSTEM_SERVICES);
Packit fabffb
		if (!applet->app_indicator)
Packit fabffb
			return FALSE;
Packit fabffb
		app_indicator_set_title(applet->app_indicator, _("Network"));
Packit fabffb
		applet_schedule_update_menu (applet);
Packit fabffb
	}
Packit fabffb
#endif  /* WITH_APPINDICATOR */
Packit fabffb
Packit fabffb
	/* Fall back to status icon if indicator isn't enabled or built */
Packit fabffb
	if (!INDICATOR_ENABLED (applet)) {
Packit fabffb
		applet->status_icon = gtk_status_icon_new ();
Packit fabffb
Packit fabffb
		if (shell_debug)
Packit fabffb
			gtk_status_icon_set_name (applet->status_icon, "adsfasdfasdfadfasdf");
Packit fabffb
Packit fabffb
		g_signal_connect (applet->status_icon, "notify::screen",
Packit fabffb
				  G_CALLBACK (status_icon_screen_changed_cb), applet);
Packit fabffb
		g_signal_connect (applet->status_icon, "size-changed",
Packit fabffb
				  G_CALLBACK (status_icon_size_changed_cb), applet);
Packit fabffb
		g_signal_connect (applet->status_icon, "activate",
Packit fabffb
				  G_CALLBACK (status_icon_activate_cb), applet);
Packit fabffb
		g_signal_connect (applet->status_icon, "popup-menu",
Packit fabffb
				  G_CALLBACK (status_icon_popup_menu_cb), applet);
Packit fabffb
Packit fabffb
		menu = GTK_MENU (gtk_menu_new ());
Packit fabffb
		nma_context_menu_populate (applet, menu);
Packit fabffb
		applet->context_menu = GTK_WIDGET (menu);
Packit fabffb
		if (!applet->context_menu)
Packit fabffb
			return FALSE;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	return TRUE;
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_embedded_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
Packit fabffb
{
Packit fabffb
	gboolean embedded = gtk_status_icon_is_embedded (GTK_STATUS_ICON (object));
Packit fabffb
Packit fabffb
	g_debug ("applet now %s the notification area",
Packit fabffb
	         embedded ? "embedded in" : "removed from");
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
register_agent (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	GError *error = NULL;
Packit fabffb
Packit fabffb
	g_return_if_fail (!applet->agent);
Packit fabffb
Packit fabffb
	applet->agent = applet_agent_new (&error);
Packit fabffb
	if (!applet->agent) {
Packit fabffb
		if (!error)
Packit fabffb
			error = g_error_new (NM_SECRET_AGENT_ERROR,
Packit fabffb
			                     NM_SECRET_AGENT_ERROR_FAILED,
Packit fabffb
			                     "Could not register secret agent");
Packit fabffb
		g_warning ("%s", error->message);
Packit fabffb
		g_error_free (error);
Packit fabffb
		return;
Packit fabffb
	}
Packit fabffb
	g_assert (applet->agent);
Packit fabffb
	g_signal_connect (applet->agent, APPLET_AGENT_GET_SECRETS,
Packit fabffb
	                  G_CALLBACK (applet_agent_get_secrets_cb), applet);
Packit fabffb
	g_signal_connect (applet->agent, APPLET_AGENT_CANCEL_SECRETS,
Packit fabffb
	                  G_CALLBACK (applet_agent_cancel_secrets_cb), applet);
Packit fabffb
Packit fabffb
	if (INDICATOR_ENABLED (applet)) {
Packit fabffb
		/* Watch for new connections */
Packit fabffb
		g_signal_connect_swapped (applet->nm_client, NM_CLIENT_CONNECTION_ADDED,
Packit fabffb
		                          G_CALLBACK (applet_schedule_update_menu),
Packit fabffb
		                          applet);
Packit fabffb
	}
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_gsettings_show_changed (GSettings *settings,
Packit fabffb
                               gchar *key,
Packit fabffb
                               gpointer user_data)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (user_data);
Packit fabffb
Packit fabffb
	g_return_if_fail (NM_IS_APPLET(applet));
Packit fabffb
	g_return_if_fail (key != NULL);
Packit fabffb
Packit fabffb
	applet->visible = g_settings_get_boolean (settings, key);
Packit fabffb
Packit fabffb
	if (applet->status_icon)
Packit fabffb
		gtk_status_icon_set_visible (applet->status_icon, applet->visible);
Packit fabffb
}
Packit fabffb
Packit fabffb
/****************************************************************/
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_activate (GApplication *app, gpointer user_data)
Packit fabffb
{
Packit fabffb
	/* Nothing to do, but glib requires this handler */
Packit fabffb
}
Packit fabffb
Packit fabffb
static void
Packit fabffb
applet_startup (GApplication *app, gpointer user_data)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (app);
Packit fabffb
	gs_free_error GError *error = NULL;
Packit fabffb
Packit fabffb
	g_set_application_name (_("NetworkManager Applet"));
Packit fabffb
	gtk_window_set_default_icon_name ("network-workgroup");
Packit fabffb
Packit fabffb
	applet->info_dialog_ui = gtk_builder_new ();
Packit fabffb
Packit fabffb
	if (!gtk_builder_add_from_resource (applet->info_dialog_ui, "/org/freedesktop/network-manager-applet/info.ui", &error)) {
Packit fabffb
		g_warning ("Could not load info dialog UI file: %s", error->message);
Packit fabffb
		g_application_quit (app);
Packit fabffb
		return;
Packit fabffb
	}
Packit fabffb
Packit fabffb
	applet->gsettings = g_settings_new (APPLET_PREFS_SCHEMA);
Packit fabffb
	applet->visible = g_settings_get_boolean (applet->gsettings, PREF_SHOW_APPLET);
Packit fabffb
	g_signal_connect (applet->gsettings, "changed::show-applet",
Packit fabffb
	                  G_CALLBACK (applet_gsettings_show_changed), applet);
Packit fabffb
Packit fabffb
	foo_client_setup (applet);
Packit fabffb
Packit fabffb
	/* Load pixmaps and create applet widgets */
Packit fabffb
	if (!setup_widgets (applet)) {
Packit fabffb
		g_warning ("Could not initialize applet widgets.");
Packit fabffb
		g_application_quit (app);
Packit fabffb
		return;
Packit fabffb
	}
Packit fabffb
	g_assert (INDICATOR_ENABLED (applet) || applet->status_icon);
Packit fabffb
Packit fabffb
	applet->icon_cache = g_hash_table_new_full (g_str_hash,
Packit fabffb
	                                            g_str_equal,
Packit fabffb
	                                            g_free,
Packit fabffb
	                                            nm_g_object_unref);
Packit fabffb
	nma_icons_init (applet);
Packit fabffb
Packit fabffb
	if (!notify_is_initted ())
Packit fabffb
		notify_init ("NetworkManager");
Packit fabffb
Packit fabffb
	/* Initialize device classes */
Packit fabffb
	applet->ethernet_class = applet_device_ethernet_get_class (applet);
Packit fabffb
	g_assert (applet->ethernet_class);
Packit fabffb
Packit fabffb
	applet->wifi_class = applet_device_wifi_get_class (applet);
Packit fabffb
	g_assert (applet->wifi_class);
Packit fabffb
Packit fabffb
#if WITH_WWAN
Packit fabffb
	applet->broadband_class = applet_device_broadband_get_class (applet);
Packit fabffb
	g_assert (applet->broadband_class);
Packit fabffb
#endif
Packit fabffb
Packit fabffb
	applet->bt_class = applet_device_bt_get_class (applet);
Packit fabffb
	g_assert (applet->bt_class);
Packit fabffb
Packit fabffb
#if WITH_WWAN
Packit fabffb
	mm1_client_setup (applet);
Packit fabffb
#endif
Packit fabffb
Packit fabffb
	if (applet->status_icon) {
Packit fabffb
		/* Track embedding to help debug issues where user has removed the
Packit fabffb
		 * notification area applet from the panel, and thus nm-applet too.
Packit fabffb
		 */
Packit fabffb
		g_signal_connect (applet->status_icon, "notify::embedded",
Packit fabffb
			              G_CALLBACK (applet_embedded_cb), NULL);
Packit fabffb
		applet_embedded_cb (G_OBJECT (applet->status_icon), NULL, NULL);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	if (with_agent)
Packit fabffb
		register_agent (applet);
Packit fabffb
Packit fabffb
	g_application_hold (G_APPLICATION (applet));
Packit fabffb
}
Packit fabffb
Packit fabffb
static void finalize (GObject *object)
Packit fabffb
{
Packit fabffb
	NMApplet *applet = NM_APPLET (object);
Packit fabffb
Packit fabffb
	g_slice_free (NMADeviceClass, applet->ethernet_class);
Packit fabffb
	g_slice_free (NMADeviceClass, applet->wifi_class);
Packit fabffb
#if WITH_WWAN
Packit fabffb
	g_slice_free (NMADeviceClass, applet->broadband_class);
Packit fabffb
#endif
Packit fabffb
	g_slice_free (NMADeviceClass, applet->bt_class);
Packit fabffb
Packit fabffb
	nm_clear_g_source (&applet->update_icon_id);
Packit fabffb
	nm_clear_g_source (&applet->wifi_scan_id);
Packit fabffb
Packit fabffb
#ifdef WITH_APPINDICATOR
Packit fabffb
	g_clear_object (&applet->app_indicator);
Packit fabffb
#endif /* WITH_APPINDICATOR */
Packit fabffb
	nm_clear_g_source (&applet->update_menu_id);
Packit fabffb
Packit fabffb
	g_clear_object (&applet->status_icon);
Packit fabffb
	g_clear_object (&applet->menu);
Packit fabffb
	g_clear_pointer (&applet->icon_cache, g_hash_table_destroy);
Packit fabffb
	g_clear_object (&applet->fallback_icon);
Packit fabffb
	g_free (applet->tip);
Packit fabffb
	nma_icons_free (applet);
Packit fabffb
Packit fabffb
	while (g_slist_length (applet->secrets_reqs))
Packit fabffb
		applet_secrets_request_free ((SecretsRequest *) applet->secrets_reqs->data);
Packit fabffb
Packit fabffb
	if (applet->notification) {
Packit fabffb
		notify_notification_close (applet->notification, NULL);
Packit fabffb
		g_object_unref (applet->notification);
Packit fabffb
	}
Packit fabffb
Packit fabffb
	g_clear_object (&applet->info_dialog_ui);
Packit fabffb
	g_clear_object (&applet->gsettings);
Packit fabffb
	g_clear_object (&applet->nm_client);
Packit fabffb
Packit fabffb
#if WITH_WWAN
Packit fabffb
	g_clear_object (&applet->mm1);
Packit fabffb
#endif
Packit fabffb
Packit fabffb
	g_clear_object (&applet->agent);
Packit fabffb
Packit fabffb
	G_OBJECT_CLASS (nma_parent_class)->finalize (object);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void nma_init (NMApplet *applet)
Packit fabffb
{
Packit fabffb
	applet->icon_size = 16;
Packit fabffb
Packit fabffb
	g_signal_connect (applet, "startup", G_CALLBACK (applet_startup), NULL);
Packit fabffb
	g_signal_connect (applet, "activate", G_CALLBACK (applet_activate), NULL);
Packit fabffb
}
Packit fabffb
Packit fabffb
static void nma_class_init (NMAppletClass *klass)
Packit fabffb
{
Packit fabffb
	GObjectClass *oclass = G_OBJECT_CLASS (klass);
Packit fabffb
Packit fabffb
	oclass->finalize = finalize;
Packit fabffb
}
Packit fabffb