From 971732aec871c103a6d0d12f4a49a7f0f2e53cbc Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 4 Oct 2022 11:15:19 +0200 Subject: applet: replace libnotify with GNotification The libnotify's notify_notification_show() does a blocking D-Bus call. In fact, one fine gentleman's nm-applet got stuck for many seconds because the bus activation aparatus in his computer was not properly greased. Let's do away with this absolute monstrosity of a library by using the desktop notification API provided by GLib since 2.40. It's simpler, fully asynchronous and in addition to freedesktop notification API it can interface with Gtk and Flatpak portal one. --- config.h.meson | 3 - configure.ac | 13 +-- meson.build | 11 +-- scripts/gitlab-ci.sh | 1 - src/applet-device-broadband.c | 30 +++---- src/applet-device-bt.c | 10 +-- src/applet-device-ethernet.c | 10 +-- src/applet-device-wifi.c | 31 ++------ src/applet.c | 179 ++++++++++++------------------------------ src/applet.h | 21 +---- src/meson.build | 1 - src/utils/utils.c | 2 +- src/utils/utils.h | 2 +- 13 files changed, 95 insertions(+), 219 deletions(-) diff --git a/config.h.meson b/config.h.meson index 41246fc0..205a0189 100644 --- a/config.h.meson +++ b/config.h.meson @@ -1,9 +1,6 @@ /* Gettext package */ #mesondefine GETTEXT_PACKAGE -/* Define if you have libnotify 0.7 or later */ -#mesondefine HAVE_LIBNOTIFY_07 - /* ISO codes prefix */ #mesondefine ISO_CODES_PREFIX diff --git a/configure.ac b/configure.ac index c8968c00..c2ba14ea 100644 --- a/configure.ac +++ b/configure.ac @@ -59,9 +59,9 @@ GETTEXT_PACKAGE=nm-applet AC_SUBST(GETTEXT_PACKAGE) AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [Gettext package]) -PKG_CHECK_MODULES(LIBNM, [libnm >= 1.15 gio-2.0 >= 2.38 gmodule-export-2.0]) -LIBNM_CFLAGS="$LIBNM_CFLAGS -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_38" -LIBNM_CFLAGS="$LIBNM_CFLAGS -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_38" +PKG_CHECK_MODULES(LIBNM, [libnm >= 1.15 gio-2.0 >= 2.40 gmodule-export-2.0]) +LIBNM_CFLAGS="$LIBNM_CFLAGS -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_40" +LIBNM_CFLAGS="$LIBNM_CFLAGS -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_40" LIBNM_CFLAGS="$LIBNM_CFLAGS -DNM_VERSION_MIN_REQUIRED=NM_VERSION_1_16" LIBNM_CFLAGS="$LIBNM_CFLAGS -DNM_VERSION_MAX_ALLOWED=NM_VERSION_1_16" @@ -70,13 +70,6 @@ LIBNMA_CFLAGS="$LIBNMA_CFLAGS -DNMA_VERSION_MIN_REQUIRED=NMA_VERSION_1_8_28" PKG_CHECK_MODULES(LIBSECRET, [libsecret-1 >= 0.18]) -# Check for libnotify >= 0.7 -PKG_CHECK_MODULES(LIBNOTIFY_07, [libnotify >= 0.7], [have_libnotify_07=yes],[have_libnotify_07=no]) -if test x"$have_libnotify_07" = "xyes"; then - AC_DEFINE(HAVE_LIBNOTIFY_07, 1, [Define if you have libnotify 0.7 or later]) -fi -PKG_CHECK_MODULES(NOTIFY, [libnotify >= 0.4.3]) - PKG_CHECK_MODULES(GTK3, gtk+-3.0 >= 3.10) GTK3_CFLAGS="$GTK3_CFLAGS -DGDK_VERSION_MIN_REQUIRED=GDK_VERSION_3_10 -DGDK_VERSION_MAX_ALLOWED=GDK_VERSION_3_10" diff --git a/meson.build b/meson.build index babc6de2..1052d3f2 100644 --- a/meson.build +++ b/meson.build @@ -104,7 +104,7 @@ add_project_link_arguments(common_ldflags, language: 'c') linker_script_ver = join_paths(meson.source_root(), 'linker-script-binary.ver') -gio_dep = dependency('gio-2.0', version: '>= 2.38') +gio_dep = dependency('gio-2.0', version: '>= 2.40') gmodule_export_dep = dependency('gmodule-export-2.0') libsecret_dep = dependency('libsecret-1', version: '>= 0.18') libnma_dep = dependency('libnma', version: '>= 1.8.27') @@ -125,11 +125,6 @@ gtk_dep = declare_dependency( # Check for gudev gudev_dep = dependency('gudev-1.0', version: '>= 147') -# Check for libnotify >= 0.7 -libnotify_dep = dependency('libnotify', version: '>= 0.4.3') -config_h.set10('HAVE_LIBNOTIFY_07', libnotify_dep.found() and libnotify_dep.version().version_compare('>= 0.7'), - description: 'Define if you have libnotify 0.7 or later') - # API documentation nm_req_version = '>= 1.7' @@ -140,8 +135,8 @@ deps = [ ] cflags = [ - '-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_38', - '-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_38', + '-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_40', + '-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_40', '-DNM_VERSION_MIN_REQUIRED=NM_VERSION_1_16', '-DNM_VERSION_MAX_ALLOWED=NM_VERSION_1_16', '-DNMA_VERSION_MIN_REQUIRED=NMA_VERSION_1_8_28', diff --git a/scripts/gitlab-ci.sh b/scripts/gitlab-ci.sh index f5a22caf..fe8acfcf 100755 --- a/scripts/gitlab-ci.sh +++ b/scripts/gitlab-ci.sh @@ -27,7 +27,6 @@ fedora_pkg_minimal() { glib2-devel \ gtk3-devel \ libgudev1-devel \ - libnotify-devel \ libsecret-devel \ libtool \ pkgconfig \ diff --git a/src/applet-device-broadband.c b/src/applet-device-broadband.c index 9c47318a..6315eaba 100644 --- a/src/applet-device-broadband.c +++ b/src/applet-device-broadband.c @@ -805,11 +805,11 @@ notify_connected (NMDevice *device, const char *msg, NMApplet *applet) { - applet_do_notify_with_pref (applet, - _("Connection Established"), - msg ? msg : _("You are now connected to the Mobile Broadband network."), - "nm-device-wwan", - PREF_DISABLE_CONNECTED_NOTIFICATIONS); + applet_do_notify (applet, + _("Connection Established"), + msg ? msg : _("You are now connected to the Mobile Broadband network."), + "nm-device-wwan", + PREF_DISABLE_CONNECTED_NOTIFICATIONS); } /********************************************************************/ @@ -946,17 +946,17 @@ modem_state_changed (MMModem *object, /* Notify about new registration info */ mb_state = broadband_state_to_mb_state (info); if (mb_state == MB_STATE_HOME) { - applet_do_notify_with_pref (info->applet, - _("Mobile Broadband network."), - _("You are now registered on the home network."), - signal_strength_icon, - PREF_DISABLE_CONNECTED_NOTIFICATIONS); + applet_do_notify (info->applet, + _("Mobile Broadband network."), + _("You are now registered on the home network."), + signal_strength_icon, + PREF_DISABLE_CONNECTED_NOTIFICATIONS); } else if (mb_state == MB_STATE_ROAMING) { - applet_do_notify_with_pref (info->applet, - _("Mobile Broadband network."), - _("You are now registered on a roaming network."), - signal_strength_icon, - PREF_DISABLE_CONNECTED_NOTIFICATIONS); + applet_do_notify (info->applet, + _("Mobile Broadband network."), + _("You are now registered on a roaming network."), + signal_strength_icon, + PREF_DISABLE_CONNECTED_NOTIFICATIONS); } } } diff --git a/src/applet-device-bt.c b/src/applet-device-bt.c index a78f1068..6aed1bb4 100644 --- a/src/applet-device-bt.c +++ b/src/applet-device-bt.c @@ -71,11 +71,11 @@ bt_notify_connected (NMDevice *device, const char *msg, NMApplet *applet) { - applet_do_notify_with_pref (applet, - _("Connection Established"), - msg ? msg : _("You are now connected to the mobile broadband network."), - "nm-device-wwan", - PREF_DISABLE_CONNECTED_NOTIFICATIONS); + applet_do_notify (applet, + _("Connection Established"), + msg ? msg : _("You are now connected to the mobile broadband network."), + "nm-device-wwan", + PREF_DISABLE_CONNECTED_NOTIFICATIONS); } static void diff --git a/src/applet-device-ethernet.c b/src/applet-device-ethernet.c index 52f70a1d..9885efef 100644 --- a/src/applet-device-ethernet.c +++ b/src/applet-device-ethernet.c @@ -120,11 +120,11 @@ ethernet_notify_connected (NMDevice *device, const char *msg, NMApplet *applet) { - applet_do_notify_with_pref (applet, - _("Connection Established"), - msg ? msg : _("You are now connected to the ethernet network."), - "nm-device-wired", - PREF_DISABLE_CONNECTED_NOTIFICATIONS); + applet_do_notify (applet, + _("Connection Established"), + msg ? msg : _("You are now connected to the ethernet network."), + "nm-device-wired", + PREF_DISABLE_CONNECTED_NOTIFICATIONS); } static void diff --git a/src/applet-device-wifi.c b/src/applet-device-wifi.c index 0a0783b9..aa3abffa 100644 --- a/src/applet-device-wifi.c +++ b/src/applet-device-wifi.c @@ -980,22 +980,6 @@ notify_ap_prop_changed_cb (NMAccessPoint *ap, } } -static void -wifi_available_dont_show_cb (NotifyNotification *notify, - gchar *id, - gpointer user_data) -{ - NMApplet *applet = NM_APPLET (user_data); - - if (!id || strcmp (id, "dont-show")) - return; - - g_settings_set_boolean (applet->gsettings, - PREF_SUPPRESS_WIFI_NETWORKS_AVAILABLE, - TRUE); -} - - struct ap_notification_data { NMApplet *applet; @@ -1079,14 +1063,11 @@ idle_check_avail_access_point_notification (gpointer datap) data->last_notification_time = timeval.tv_sec; applet_do_notify (applet, - NOTIFY_URGENCY_LOW, _("Wi-Fi Networks Available"), _("Use the network menu to connect to a Wi-Fi network"), "nm-device-wireless", - "dont-show", - _("Don’t show this message again"), - wifi_available_dont_show_cb, - applet); + PREF_SUPPRESS_WIFI_NETWORKS_AVAILABLE); + return FALSE; } @@ -1266,9 +1247,11 @@ wifi_notify_connected (NMDevice *device, signal_strength_icon = mobile_helper_get_quality_icon_name (nm_access_point_get_strength (ap)); ssid_msg = g_strdup_printf (_("You are now connected to the Wi-Fi network “%s”."), esc_ssid); - applet_do_notify_with_pref (applet, _("Connection Established"), - ssid_msg, signal_strength_icon, - PREF_DISABLE_CONNECTED_NOTIFICATIONS); + applet_do_notify (applet, + _("Connection Established"), + ssid_msg, + signal_strength_icon, + PREF_DISABLE_CONNECTED_NOTIFICATIONS); g_free (ssid_msg); g_free (esc_ssid); } diff --git a/src/applet.c b/src/applet.c index d9eb30e5..5c968ffe 100644 --- a/src/applet.c +++ b/src/applet.c @@ -21,7 +21,6 @@ #include #include #include -#include #include "applet.h" #include "applet-device-bt.h" @@ -685,58 +684,23 @@ applet_menu_item_create_device_item_helper (NMDevice *device, return item; } -static void -applet_clear_notify (NMApplet *applet) -{ - if (applet->notification == NULL) - return; - - notify_notification_close (applet->notification, NULL); - g_object_unref (applet->notification); - applet->notification = NULL; -} - -static gboolean -applet_notify_server_has_actions (void) -{ - static gboolean has_actions = FALSE; - static gboolean initialized = FALSE; - GList *server_caps, *iter; - - if (initialized) - return has_actions; - initialized = TRUE; - - server_caps = notify_get_server_caps(); - for (iter = server_caps; iter; iter = g_list_next (iter)) { - if (!strcmp ((const char *) iter->data, NOTIFY_CAPS_ACTIONS_KEY)) { - has_actions = TRUE; - break; - } - } - g_list_free_full (server_caps, g_free); - - return has_actions; -} - void applet_do_notify (NMApplet *applet, - NotifyUrgency urgency, - const char *summary, - const char *message, - const char *icon, - const char *action1, - const char *action1_label, - NotifyActionCallback action1_cb, - gpointer action1_user_data) -{ - NotifyNotification *notify; - GError *error = NULL; + const char *title, + const char *body, + const char *icon_name, + const char *pref) +{ + gs_unref_object GNotification *notify = NULL; + GIcon *icon; char *escaped; g_return_if_fail (applet != NULL); - g_return_if_fail (summary != NULL); - g_return_if_fail (message != NULL); + g_return_if_fail (title != NULL); + g_return_if_fail (body != NULL); + + if (pref && g_settings_get_boolean (applet->gsettings, pref)) + return; if (INDICATOR_ENABLED (applet)) { #ifdef WITH_APPINDICATOR @@ -752,73 +716,24 @@ applet_do_notify (NMApplet *applet, if (!applet->agent) return; - applet_clear_notify (applet); + notify = g_notification_new (title); - escaped = utils_escape_notify_message (message); - notify = notify_notification_new (summary, - escaped, - icon ? icon : "network-workgroup" -#if HAVE_LIBNOTIFY_07 - ); -#else - , NULL); -#endif + escaped = utils_escape_notify_body (body); + g_notification_set_body (notify, escaped); g_free (escaped); - applet->notification = notify; -#if HAVE_LIBNOTIFY_07 - notify_notification_set_hint (notify, "transient", g_variant_new_boolean (TRUE)); - notify_notification_set_hint (notify, "desktop-entry", g_variant_new_string ("nm-applet")); -#else - notify_notification_attach_to_status_icon (notify, applet->status_icon); -#endif - notify_notification_set_urgency (notify, urgency); - notify_notification_set_timeout (notify, NOTIFY_EXPIRES_DEFAULT); + icon = g_themed_icon_new (icon_name ?: "network-workgroup"); + g_notification_set_icon (notify, icon); + g_object_unref (icon); - if (applet_notify_server_has_actions () && action1) { - notify_notification_clear_actions (notify); - notify_notification_add_action (notify, action1, action1_label, - action1_cb, action1_user_data, NULL); - } + if (pref) { + g_notification_add_button_with_target (notify, + _("Don’t show this message again"), + "app.enable-pref", "s", pref); - if (!notify_notification_show (notify, &error)) { - g_warning ("Failed to show notification: %s", - error && error->message ? error->message : "(unknown)"); - g_clear_error (&error); } -} -static void -notify_dont_show_cb (NotifyNotification *notify, - gchar *id, - gpointer user_data) -{ - NMApplet *applet = NM_APPLET (user_data); - - if (!id) - return; - - if ( strcmp (id, PREF_DISABLE_CONNECTED_NOTIFICATIONS) - && strcmp (id, PREF_DISABLE_DISCONNECTED_NOTIFICATIONS) - && strcmp (id, PREF_DISABLE_VPN_NOTIFICATIONS)) - return; - - g_settings_set_boolean (applet->gsettings, id, TRUE); -} - -void applet_do_notify_with_pref (NMApplet *applet, - const char *summary, - const char *message, - const char *icon, - const char *pref) -{ - if (g_settings_get_boolean (applet->gsettings, pref)) - return; - - applet_do_notify (applet, NOTIFY_URGENCY_LOW, summary, message, icon, pref, - _("Don’t show this message again"), - notify_dont_show_cb, - applet); + g_application_send_notification (G_APPLICATION (applet), "nm-applet", notify); } static gboolean @@ -966,8 +881,8 @@ vpn_active_connection_state_changed (NMVpnConnection *vpn, msg = g_strdup (_("VPN connection has been successfully established.\n")); title = _("VPN Login Message"); - applet_do_notify_with_pref (applet, title, msg, "gnome-lockscreen", - PREF_DISABLE_VPN_NOTIFICATIONS); + applet_do_notify (applet, title, msg, "gnome-lockscreen", + PREF_DISABLE_VPN_NOTIFICATIONS); g_free (msg); break; case NM_ACTIVE_CONNECTION_STATE_DEACTIVATED: @@ -975,8 +890,8 @@ vpn_active_connection_state_changed (NMVpnConnection *vpn, break; title = _("VPN Connection Failed"); msg = make_active_failure_message (NM_ACTIVE_CONNECTION (vpn), reason, applet); - applet_do_notify_with_pref (applet, title, msg, "gnome-lockscreen", - PREF_DISABLE_VPN_NOTIFICATIONS); + applet_do_notify (applet, title, msg, "gnome-lockscreen", + PREF_DISABLE_VPN_NOTIFICATIONS); g_free (msg); break; default: @@ -1024,8 +939,8 @@ activate_vpn_cb (GObject *client, info->vpn_name, error->message); } - applet_do_notify_with_pref (info->applet, title, msg, "gnome-lockscreen", - PREF_DISABLE_VPN_NOTIFICATIONS); + applet_do_notify (info->applet, title, msg, "gnome-lockscreen", + PREF_DISABLE_VPN_NOTIFICATIONS); g_warning ("VPN Connection activation failed: (%s) %s", name, error->message); g_free (msg); g_free (name); @@ -2283,10 +2198,10 @@ foo_client_state_changed_cb (NMClient *client, GParamSpec *pspec, gpointer user_ switch (nm_client_get_state (client)) { case NM_STATE_DISCONNECTED: - applet_do_notify_with_pref (applet, _("Disconnected"), - _("The network connection has been disconnected."), - "nm-no-connection", - PREF_DISABLE_DISCONNECTED_NOTIFICATIONS); + applet_do_notify (applet, _("Disconnected"), + _("The network connection has been disconnected."), + "nm-no-connection", + PREF_DISABLE_DISCONNECTED_NOTIFICATIONS); break; default: break; @@ -3196,7 +3111,7 @@ status_icon_activate_cb (GtkStatusIcon *icon, NMApplet *applet) /* Have clicking on the applet act also as acknowledgement * of the notification. */ - applet_clear_notify (applet); + g_application_withdraw_notification (G_APPLICATION (applet), "nm-applet"); applet_start_wifi_scan (applet, NULL); @@ -3228,7 +3143,7 @@ status_icon_popup_menu_cb (GtkStatusIcon *icon, /* Have clicking on the applet act also as acknowledgement * of the notification. */ - applet_clear_notify (applet); + g_application_withdraw_notification (G_APPLICATION (applet), "nm-applet"); nma_context_menu_update (applet); gtk_menu_popup (GTK_MENU (applet->context_menu), NULL, NULL, @@ -3337,6 +3252,19 @@ applet_gsettings_show_changed (GSettings *settings, /****************************************************************/ +static void +applet_enable_pref (GSimpleAction *action, GVariant *parameter, gpointer user_data) +{ + g_settings_set_boolean (NM_APPLET (user_data)->gsettings, + g_variant_get_string (parameter, NULL), + TRUE); +} + +static GActionEntry app_entries[] = +{ + { "app.enable-pref", applet_enable_pref, "s" }, +}; + static void applet_activate (GApplication *app, gpointer user_data) { @@ -3352,6 +3280,9 @@ applet_startup (GApplication *app, gpointer user_data) g_set_application_name (_("NetworkManager Applet")); gtk_window_set_default_icon_name ("network-workgroup"); + g_action_map_add_action_entries (G_ACTION_MAP (app), app_entries, + G_N_ELEMENTS (app_entries), app); + applet->info_dialog_ui = gtk_builder_new (); if (!gtk_builder_add_from_resource (applet->info_dialog_ui, "/org/freedesktop/network-manager-applet/info.ui", &error)) { @@ -3381,9 +3312,6 @@ applet_startup (GApplication *app, gpointer user_data) nm_g_object_unref); nma_icons_init (applet); - if (!notify_is_initted ()) - notify_init ("NetworkManager"); - /* Initialize device classes */ applet->ethernet_class = applet_device_ethernet_get_class (applet); g_assert (applet->ethernet_class); @@ -3447,11 +3375,6 @@ static void finalize (GObject *object) while (g_slist_length (applet->secrets_reqs)) applet_secrets_request_free ((SecretsRequest *) applet->secrets_reqs->data); - if (applet->notification) { - notify_notification_close (applet->notification, NULL); - g_object_unref (applet->notification); - } - g_clear_object (&applet->info_dialog_ui); g_clear_object (&applet->gsettings); g_clear_object (&applet->nm_client); diff --git a/src/applet.h b/src/applet.h index 2bc2246f..03566595 100644 --- a/src/applet.h +++ b/src/applet.h @@ -15,8 +15,6 @@ #include -#include - #ifdef WITH_APPINDICATOR #if USE_AYATANA_INDICATORS #include @@ -138,7 +136,6 @@ typedef struct { GtkWidget * connections_menu_item; GtkBuilder * info_dialog_ui; - NotifyNotification* notification; /* Tracker objects for secrets requests */ GSList * secrets_reqs; @@ -261,20 +258,10 @@ NMRemoteConnection *applet_get_exported_connection_for_device (NMDevice *device, NMDevice *applet_get_device_for_connection (NMApplet *applet, NMConnection *connection); void applet_do_notify (NMApplet *applet, - NotifyUrgency urgency, - const char *summary, - const char *message, - const char *icon, - const char *action1, - const char *action1_label, - NotifyActionCallback action1_cb, - gpointer action1_user_data); - -void applet_do_notify_with_pref (NMApplet *applet, - const char *summary, - const char *message, - const char *icon, - const char *pref); + const char *title, + const char *body, + const char *icon_name, + const char *pref); GtkWidget * applet_new_menu_item_helper (NMConnection *connection, NMConnection *active, diff --git a/src/meson.build b/src/meson.build index fade5afa..ce7ab94b 100644 --- a/src/meson.build +++ b/src/meson.build @@ -47,7 +47,6 @@ deps = [ gtk_dep, libnm_dep, libnma_dep, - libnotify_dep, libsecret_dep, m_dep, libutils_libnm_dep diff --git a/src/utils/utils.c b/src/utils/utils.c index c33c7bcd..5daad24f 100644 --- a/src/utils/utils.c +++ b/src/utils/utils.c @@ -116,7 +116,7 @@ static Tag escaped_tags[] = { }; char * -utils_escape_notify_message (const char *src) +utils_escape_notify_body (const char *src) { const char *p = src; GString *escaped; diff --git a/src/utils/utils.h b/src/utils/utils.h index 3192ea45..fb40421f 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -19,7 +19,7 @@ char *utils_hash_ap (GBytes *ssid, guint32 wpa_flags, guint32 rsn_flags); -char *utils_escape_notify_message (const char *src); +char *utils_escape_notify_body (const char *src); char *utils_create_mobile_connection_id (const char *provider, const char *plan_name); -- cgit v1.2.1