diff options
author | Victor Kareh <[email protected]> | 2025-08-27 21:14:05 -0400 |
---|---|---|
committer | Luke from DC <[email protected]> | 2025-10-10 02:11:17 +0000 |
commit | 8b88e829580b71f67a904266a08f0b5aef8f75bb (patch) | |
tree | ef65a7f0a739fcf858818cc6a06675150942dc48 | |
parent | fcde65c52c3ceb4c97af33679ead210b1b1d58e2 (diff) | |
download | mate-notification-daemon-8b88e829580b71f67a904266a08f0b5aef8f75bb.tar.bz2 mate-notification-daemon-8b88e829580b71f67a904266a08f0b5aef8f75bb.tar.xz |
capplet: Add notification history context module
Adds the basis for a notification management system using the D-Bus
context to display notification history in a popup.
Fixes https://github.com/mate-desktop/mate-notification-daemon/issues/74
-rw-r--r-- | src/capplet/Makefile.am | 5 | ||||
-rw-r--r-- | src/capplet/mate-notification-applet-history.c | 372 | ||||
-rw-r--r-- | src/capplet/mate-notification-applet-history.h | 59 | ||||
-rw-r--r-- | src/capplet/mate-notification-applet-menu.xml | 5 | ||||
-rw-r--r-- | src/capplet/mate-notification-applet.c | 135 |
5 files changed, 574 insertions, 2 deletions
diff --git a/src/capplet/Makefile.am b/src/capplet/Makefile.am index 4126d3f..0017ab6 100644 --- a/src/capplet/Makefile.am +++ b/src/capplet/Makefile.am @@ -47,6 +47,8 @@ libmate_notification_applet_la_SOURCES = \ mate-notification-applet.c \ mate-notification-applet-dbus.h \ mate-notification-applet-dbus.c \ + mate-notification-applet-history.h \ + mate-notification-applet-history.c \ $(NULL) libmate_notification_applet_la_CFLAGS = \ @@ -68,6 +70,8 @@ mate_notification_applet_SOURCES = \ mate-notification-applet.c \ mate-notification-applet-dbus.h \ mate-notification-applet-dbus.c \ + mate-notification-applet-history.h \ + mate-notification-applet-history.c \ $(NULL) mate_notification_applet_CFLAGS = \ @@ -109,6 +113,7 @@ EXTRA_DIST = \ mate-notification-applet-menu.xml \ mate-notification-properties.ui \ mate-notification-applet-dbus.h \ + mate-notification-applet-history.h \ $(NULL) -include $(top_srcdir)/git.mk diff --git a/src/capplet/mate-notification-applet-history.c b/src/capplet/mate-notification-applet-history.c new file mode 100644 index 0000000..cca03d6 --- /dev/null +++ b/src/capplet/mate-notification-applet-history.c @@ -0,0 +1,372 @@ +/* mate-notification-applet.c - MATE Notification Applet - History + * + * Copyright (C) 2025 MATE Developers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include "config.h" + +#include <glib/gi18n.h> +#include <gtk/gtk.h> +#include <gdk/gdkkeysyms.h> + +#include "mate-notification-applet-history.h" +#include "../common/constants.h" + +#define IMAGE_SIZE 48 + +static GtkWidget * +create_notification_icon (const gchar *icon_name) +{ + GdkPixbuf *pixbuf = NULL; + GtkWidget *image; + + if (icon_name && *icon_name) { + if (g_path_is_absolute (icon_name)) { + pixbuf = gdk_pixbuf_new_from_file_at_scale (icon_name, IMAGE_SIZE, IMAGE_SIZE, TRUE, NULL); + } else { + GtkIconTheme *theme = gtk_icon_theme_get_default (); + pixbuf = gtk_icon_theme_load_icon (theme, icon_name, IMAGE_SIZE, GTK_ICON_LOOKUP_USE_BUILTIN, NULL); + } + } + + if (pixbuf) { + image = gtk_image_new_from_pixbuf (pixbuf); + g_object_unref (pixbuf); + } else { + image = gtk_image_new_from_icon_name ("mate-notification-properties", GTK_ICON_SIZE_DIALOG); + } + + gtk_widget_set_valign (image, GTK_ALIGN_CENTER); + return image; +} + +static GtkWidget * +create_popup_window (void) +{ + GtkWidget *popup = gtk_window_new (GTK_WINDOW_POPUP); + g_object_set (popup, + "type-hint", GDK_WINDOW_TYPE_HINT_POPUP_MENU, + "skip-taskbar-hint", TRUE, + "skip-pager-hint", TRUE, + "decorated", FALSE, + "resizable", FALSE, + NULL); + gtk_container_set_border_width (GTK_CONTAINER (popup), 1); + return popup; +} + +static void +popup_destroyed_cb (GtkWidget *popup, + MateNotificationHistoryContext *context) +{ + (void) popup; + context->history_popup = NULL; +} + +static GtkWidget * +create_notification_row (guint id, const gchar *app_name, const gchar *app_icon, + const gchar *summary, const gchar *body, gint64 timestamp) +{ + GtkWidget *row, *hbox, *icon_image, *content_box; + GtkWidget *title_label, *body_label, *time_label; + GDateTime *dt; + gchar *time_str, *markup; + + /* Format timestamp */ + dt = g_date_time_new_from_unix_local (timestamp / G_TIME_SPAN_SECOND); + time_str = g_date_time_format (dt, "%H:%M"); + g_date_time_unref (dt); + + /* Create row container for the entire notification */ + row = gtk_list_box_row_new (); + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (hbox), 6); + + icon_image = create_notification_icon (app_icon); + + content_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3); + + /* Title */ + markup = g_markup_printf_escaped ("<b>%s</b>", summary ? summary : _("(No summary)")); + title_label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (title_label), markup); + gtk_widget_set_halign (title_label, GTK_ALIGN_START); + gtk_label_set_ellipsize (GTK_LABEL (title_label), PANGO_ELLIPSIZE_END); + gtk_label_set_max_width_chars (GTK_LABEL (title_label), 40); + g_free (markup); + + /* Body */ + body_label = NULL; + if (body && *body) { + body_label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (body_label), body); + gtk_widget_set_halign (body_label, GTK_ALIGN_START); + gtk_label_set_ellipsize (GTK_LABEL (body_label), PANGO_ELLIPSIZE_END); + gtk_label_set_max_width_chars (GTK_LABEL (body_label), 40); + + /* Set tooltip in case the body overflows */ + gchar *tooltip_text = g_strdup_printf ("%s\n%s", summary, body); + gtk_widget_set_tooltip_text (row, tooltip_text); + g_free (tooltip_text); + } + + /* Time and app label */ + markup = g_markup_printf_escaped ("<small>%s - %s</small>", + app_name ? app_name : _("Unknown"), + time_str); + time_label = gtk_label_new (NULL); + gtk_label_set_markup (GTK_LABEL (time_label), markup); + gtk_widget_set_halign (time_label, GTK_ALIGN_START); + g_free (markup); + g_free (time_str); + + /* Pack content box */ + gtk_box_pack_start (GTK_BOX (content_box), title_label, FALSE, FALSE, 0); + if (body_label) + gtk_box_pack_start (GTK_BOX (content_box), body_label, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (content_box), time_label, FALSE, FALSE, 0); + + /* Pack horizontal box */ + gtk_box_pack_start (GTK_BOX (hbox), icon_image, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), content_box, TRUE, TRUE, 0); + + gtk_container_add (GTK_CONTAINER (row), hbox); + + return row; +} + +static void +clear_history (GtkWidget *button, + MateNotificationHistoryContext *context) +{ + (void) button; + + /* Clear the notification history */ + if (dbus_context_clear_notification_history (context->dbus_context)) { + /* Trigger count update after clearing */ + if (context->count_update_callback) { + ((void (*)(gpointer)) context->count_update_callback) (context->count_update_user_data); + } + } + + /* Close the popup */ + if (context->history_popup) { + gtk_widget_destroy (context->history_popup); + } +} + +static void +dnd_toggle_clicked (GtkToggleButton *toggle, + MateNotificationHistoryContext *context) +{ + gboolean active = gtk_toggle_button_get_active (toggle); + + if (context->settings) { + g_settings_set_boolean (context->settings, "do-not-disturb", active); + } +} + + +MateNotificationHistoryContext * +history_context_new (MateNotificationDBusContext *dbus_context, + GtkWidget *main_widget, + GCallback count_update_callback, + gpointer count_update_user_data, + GSettings *settings) +{ + MateNotificationHistoryContext *context = g_new0 (MateNotificationHistoryContext, 1); + context->dbus_context = dbus_context; + context->main_widget = main_widget; + context->history_popup = NULL; + context->count_update_callback = count_update_callback; + context->count_update_user_data = count_update_user_data; + context->settings = settings; + return context; +} + +void +history_context_free (MateNotificationHistoryContext *context) +{ + if (context) { + if (context->history_popup) { + gtk_widget_destroy (context->history_popup); + } + g_free (context); + } +} + +void +history_context_update_dbus (MateNotificationHistoryContext *context, + MateNotificationDBusContext *dbus_context) +{ + if (context) { + context->dbus_context = dbus_context; + } +} + +void +show_notification_history (MateNotificationHistoryContext *context) +{ + GtkWidget *popup; + GtkWidget *vbox; + GtkWidget *scrolled_window; + GtkWidget *list_box; + GtkWidget *button_box; + GtkWidget *dnd_toggle; + GtkWidget *clear_button; + GtkWidget *close_button; + GVariant *result; + GVariantIter *iter; + guint id, urgency; + gchar *app_name, *app_icon, *summary, *body; + gint64 timestamp, closed_timestamp; + guint reason; + gboolean read; + gint x, y; + GdkWindow *window; + + if (!dbus_context_is_available (context->dbus_context)) { + g_warning ("Cannot show history: daemon not available"); + return; + } + + /* If popup already exists, destroy it (basically toggle off) */ + if (context->history_popup) { + gtk_widget_destroy (context->history_popup); + context->history_popup = NULL; + return; + } + + /* Get notification history from daemon */ + result = dbus_context_get_notification_history (context->dbus_context); + + if (!result) { + g_warning ("Failed to get notification history"); + return; + } + + /* Trigger count update since accessing history marks all as read */ + if (context->count_update_callback) { + ((void (*)(gpointer)) context->count_update_callback) (context->count_update_user_data); + } + + popup = create_popup_window (); + + context->history_popup = popup; + g_signal_connect (popup, "destroy", G_CALLBACK (popup_destroyed_cb), context); + + /* Create main container */ + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 12); + gtk_container_add (GTK_CONTAINER (popup), vbox); + + /* Create list box for all notifications */ + list_box = gtk_list_box_new (); + gtk_list_box_set_selection_mode (GTK_LIST_BOX (list_box), GTK_SELECTION_NONE); + + /* Get history data and add to list */ + gint notification_count = 0; + if (result) { + g_variant_get (result, "(a(ussssxxuub))", &iter); + + while (g_variant_iter_loop (iter, "(ussssxxuub)", + &id, &app_name, &app_icon, &summary, &body, + ×tamp, &closed_timestamp, &reason, &urgency, &read)) { + notification_count++; + /* Add each notification as a new row in the list */ + GtkWidget *row = create_notification_row (id, app_name, app_icon, summary, body, timestamp); + gtk_list_box_insert (GTK_LIST_BOX (list_box), row, -1); + } + + g_variant_iter_free (iter); + g_variant_unref (result); + } + + /* Add message if list is empty */ + if (gtk_list_box_get_row_at_index (GTK_LIST_BOX (list_box), 0) == NULL) { + GtkWidget *row = gtk_list_box_row_new (); + GtkWidget *label = gtk_label_new (_("No notifications")); + gtk_widget_set_sensitive (label, FALSE); + gtk_container_set_border_width (GTK_CONTAINER (row), 12); + gtk_container_add (GTK_CONTAINER (row), label); + gtk_list_box_insert (GTK_LIST_BOX (list_box), row, -1); + } + + /* Add this window for the list of notifications */ + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + /* Calculate to ensure the popup is the right height: + * 80% of screen height, with some room for buttons */ + GdkScreen *screen = gtk_widget_get_screen (context->main_widget); + gint max_content_height = (gdk_screen_get_height (screen) * 0.8) - 100; + + gint content_height = 100; /* 100px minimum */ + if (notification_count > 0) + content_height = MIN(notification_count * content_height, max_content_height); + + /* Now force the scrollable window to be the calculated height */ + gtk_scrolled_window_set_max_content_height (GTK_SCROLLED_WINDOW (scrolled_window), max_content_height); + gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (scrolled_window), content_height); + gtk_container_add (GTK_CONTAINER (scrolled_window), list_box); + + gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0); + + /* Add a box for action buttons */ + button_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + gtk_container_set_border_width (GTK_CONTAINER (button_box), 6); + + /* DND toggle first */ + dnd_toggle = gtk_check_button_new_with_label (_("Do not disturb")); + gtk_widget_set_halign (dnd_toggle, GTK_ALIGN_START); + + if (context->settings) { + gboolean dnd_enabled = g_settings_get_boolean (context->settings, "do-not-disturb"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dnd_toggle), dnd_enabled); + } + + g_signal_connect (dnd_toggle, "toggled", G_CALLBACK (dnd_toggle_clicked), context); + gtk_box_pack_start (GTK_BOX (button_box), dnd_toggle, FALSE, FALSE, 0); + + /* Spacer to push buttons to the right */ + GtkWidget *spacer = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_pack_start (GTK_BOX (button_box), spacer, TRUE, TRUE, 0); + + /* Then the action buttons */ + clear_button = gtk_button_new_with_label (_("Clear All")); + close_button = gtk_button_new_with_label (_("Close")); + + g_signal_connect (clear_button, "clicked", G_CALLBACK (clear_history), context); + g_signal_connect_swapped (close_button, "clicked", G_CALLBACK (gtk_widget_destroy), popup); + + gtk_box_pack_end (GTK_BOX (button_box), close_button, FALSE, FALSE, 0); + gtk_box_pack_end (GTK_BOX (button_box), clear_button, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), button_box, FALSE, FALSE, 0); + + /* Place popup window below the applet */ + window = gtk_widget_get_window (context->main_widget); + if (window) { + gdk_window_get_origin (window, &x, &y); + gtk_window_move (GTK_WINDOW (popup), x, y + gtk_widget_get_allocated_height (context->main_widget)); + } + + /* Set popup size based on content (with space for buttons) */ + gtk_window_set_default_size (GTK_WINDOW (popup), 450, content_height + 100); + gtk_widget_show_all (popup); +} diff --git a/src/capplet/mate-notification-applet-history.h b/src/capplet/mate-notification-applet-history.h new file mode 100644 index 0000000..37d0c31 --- /dev/null +++ b/src/capplet/mate-notification-applet-history.h @@ -0,0 +1,59 @@ +/* mate-notification-applet.c - MATE Notification Applet - History + * + * Copyright (C) 2025 MATE Developers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef __MATE_NOTIFICATION_APPLET_HISTORY_H__ +#define __MATE_NOTIFICATION_APPLET_HISTORY_H__ + +#include <gtk/gtk.h> +#include <gio/gio.h> +#include <mate-panel-applet.h> + +#include "mate-notification-applet-dbus.h" + +G_BEGIN_DECLS + +/* History context structure */ +typedef struct { + MateNotificationDBusContext *dbus_context; + GtkWidget *main_widget; + GtkWidget *history_popup; + GCallback count_update_callback; + gpointer count_update_user_data; + GSettings *settings; +} MateNotificationHistoryContext; + +/* History popup functions */ +void show_notification_history (MateNotificationHistoryContext *context); + +/* Context creation/cleanup */ +MateNotificationHistoryContext *history_context_new (MateNotificationDBusContext *dbus_context, + GtkWidget *main_widget, + GCallback count_update_callback, + gpointer count_update_user_data, + GSettings *settings); +void history_context_free (MateNotificationHistoryContext *context); + +/* Context update functions */ +void history_context_update_dbus (MateNotificationHistoryContext *context, + MateNotificationDBusContext *dbus_context); + +G_END_DECLS + +#endif /* __MATE_NOTIFICATION_APPLET_HISTORY_H__ */ diff --git a/src/capplet/mate-notification-applet-menu.xml b/src/capplet/mate-notification-applet-menu.xml index cab30ac..4b41d57 100644 --- a/src/capplet/mate-notification-applet-menu.xml +++ b/src/capplet/mate-notification-applet-menu.xml @@ -1,3 +1,8 @@ <menuitem name="DoNotDisturb Item" action="DoNotDisturb" /> +<separator /> +<menuitem name="ShowHistory Item" action="ShowHistory" /> +<menuitem name="ClearHistory Item" action="ClearHistory" /> +<menuitem name="MarkAllRead Item" action="MarkAllRead" /> +<separator /> <menuitem name="Preferences Item" action="Preferences" /> <menuitem name="About Item" action="About" /> diff --git a/src/capplet/mate-notification-applet.c b/src/capplet/mate-notification-applet.c index f7d02e0..c9f18e5 100644 --- a/src/capplet/mate-notification-applet.c +++ b/src/capplet/mate-notification-applet.c @@ -32,6 +32,7 @@ #include "constants.h" #include "mate-notification-applet-dbus.h" +#include "mate-notification-applet-history.h" typedef struct { @@ -41,8 +42,11 @@ typedef struct GtkWidget *image_off; GtkActionGroup *action_group; GSettings *settings; + guint unread_count; + guint update_timer_id; MateNotificationDBusContext *dbus_context; + MateNotificationHistoryContext *history_context; } MateNotificationApplet; static void @@ -51,11 +55,37 @@ show_about (GtkAction *action, static void call_properties (GtkAction *action, MateNotificationApplet *applet); +static void +call_show_history (GtkAction *action, + MateNotificationApplet *applet); +void +call_clear_history (GtkAction *action, + MateNotificationApplet *applet); +static void +call_mark_all_read (GtkAction *action, + MateNotificationApplet *applet); +/* D-Bus and notification history functions */ static void setup_daemon_connection (MateNotificationApplet *applet); +static void +update_unread_count (MateNotificationApplet *applet); +static gboolean +periodic_update_count (MateNotificationApplet *applet); + +/* Click handler functions */ +static gboolean +applet_button_press_cb (GtkWidget *widget, + GdkEventButton *event, + MateNotificationApplet *applet); static const GtkActionEntry applet_menu_actions [] = { + { "ShowHistory", "document-open-recent", N_("_Show History"), + NULL, NULL, G_CALLBACK (call_show_history) }, + { "ClearHistory", "edit-clear", N_("_Clear History"), + NULL, NULL, G_CALLBACK (call_clear_history) }, + { "MarkAllRead", "edit-select-all", N_("_Mark All as Read"), + NULL, NULL, G_CALLBACK (call_mark_all_read) }, { "Preferences", "document-properties", N_("_Preferences"), NULL, NULL, G_CALLBACK (call_properties) }, { "About", "help-about", N_("_About"), @@ -72,16 +102,54 @@ applet_destroy (MatePanelApplet *applet_widget, { g_assert (applet); + if (applet->update_timer_id > 0) + g_source_remove (applet->update_timer_id); + if (applet->dbus_context) { dbus_context_free (applet->dbus_context); } + if (applet->history_context) { + history_context_free (applet->history_context); + } + g_object_unref (applet->settings); g_object_unref (applet->action_group); g_free (applet); } static void +call_show_history (GtkAction *action, + MateNotificationApplet *applet) +{ + (void) action; + + if (applet->history_context) + show_notification_history (applet->history_context); +} + +void +call_clear_history (GtkAction *action, + MateNotificationApplet *applet) +{ + (void) action; + + if (dbus_context_clear_notification_history (applet->dbus_context)) + update_unread_count (applet); +} + +static void +call_mark_all_read (GtkAction *action, + MateNotificationApplet *applet) +{ + (void) action; + + /* Update count after marking all as read */ + if (dbus_context_mark_all_notifications_as_read (applet->dbus_context)) + update_unread_count (applet); +} + +static void call_properties (GtkAction *action, MateNotificationApplet *applet) { @@ -175,7 +243,52 @@ applet_draw_icon (MatePanelApplet *applet_widget, static void setup_daemon_connection (MateNotificationApplet *applet) { - dbus_context_connect (applet->dbus_context); + if (dbus_context_connect (applet->dbus_context)) { + update_unread_count (applet); + } else { + applet->unread_count = 0; + } + + /* Update history context with new daemon connection */ + if (applet->history_context) { + history_context_update_dbus (applet->history_context, applet->dbus_context); + } +} + +static void +update_unread_count (MateNotificationApplet *applet) +{ + applet->unread_count = dbus_context_get_notification_count (applet->dbus_context); +} + +static gboolean +applet_button_press_cb (GtkWidget *widget, + GdkEventButton *event, + MateNotificationApplet *applet) +{ + switch (event->button) { + case 1: /* Left click */ + if (applet->history_context) { + show_notification_history (applet->history_context); + } + return TRUE; + + case 2: /* Middle click */ + case 3: /* Right click handled by context menu */ + default: + break; + } + + return FALSE; +} + +static gboolean +periodic_update_count (MateNotificationApplet *applet) +{ + if (applet && dbus_context_is_available (applet->dbus_context)) { + update_unread_count (applet); + } + return TRUE; /* Continue periodic updates */ } static MateNotificationApplet* @@ -193,8 +306,10 @@ applet_main (MatePanelApplet *applet_widget) applet->applet = applet_widget; applet->settings = g_settings_new (GSETTINGS_SCHEMA); - /* Initialize D-Bus context */ + /* Initialize D-Bus context and notification state */ applet->dbus_context = dbus_context_new (); + applet->unread_count = 0; + applet->update_timer_id = 0; #ifndef ENABLE_IN_PROCESS /* needed to clamp ourselves to the panel size */ @@ -220,6 +335,11 @@ applet_main (MatePanelApplet *applet_widget) g_settings_get_boolean (applet->settings, GSETTINGS_KEY_DO_NOT_DISTURB)); + /* click handling */ + gtk_widget_add_events (GTK_WIDGET (applet_widget), GDK_BUTTON_PRESS_MASK); + g_signal_connect (G_OBJECT (applet_widget), "button-press-event", + G_CALLBACK (applet_button_press_cb), applet); + /* set up context menu */ applet->action_group = gtk_action_group_new ("Do Not Disturb Actions"); #ifdef ENABLE_NLS @@ -250,8 +370,19 @@ applet_main (MatePanelApplet *applet_widget) g_signal_connect (G_OBJECT (applet->settings), "changed::" GSETTINGS_KEY_DO_NOT_DISTURB, G_CALLBACK (settings_changed), applet); + /* Create new history context */ + applet->history_context = history_context_new (applet->dbus_context, + GTK_WIDGET (applet->applet), + G_CALLBACK (update_unread_count), + applet, + applet->settings); + setup_daemon_connection (applet); + /* Set up periodic updates every few seconds */ +#define NOTIFICATION_UPDATE_COUNT 5 + applet->update_timer_id = g_timeout_add_seconds (NOTIFICATION_UPDATE_COUNT, (GSourceFunc) periodic_update_count, applet); + return applet; } |