[gnome-flashback] notifications: rename NdBubble to GfBubble



commit 302df76438ad7f7cba75c2fe949daffb9d701155
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Thu Feb 18 19:06:54 2016 +0200

    notifications: rename NdBubble to GfBubble
    
    In same time change parent class from GtkWindow to GfPopupWindow.

 data/theme/Adwaita/gnome-flashback-dark.css  |    3 +
 data/theme/Adwaita/gnome-flashback.css       |    3 +
 data/theme/HighContrast/gnome-flashback.css  |    3 +
 gnome-flashback/libnotifications/Makefile.am |    7 +-
 gnome-flashback/libnotifications/gf-bubble.c |  687 +++++++++++++++++++
 gnome-flashback/libnotifications/gf-bubble.h |   45 ++
 gnome-flashback/libnotifications/nd-bubble.c |  915 --------------------------
 gnome-flashback/libnotifications/nd-bubble.h |   56 --
 gnome-flashback/libnotifications/nd-queue.c  |    8 +-
 gnome-flashback/libnotifications/nd-stack.c  |   10 +-
 gnome-flashback/libnotifications/nd-stack.h  |    6 +-
 po/POTFILES.in                               |    2 +-
 12 files changed, 759 insertions(+), 986 deletions(-)
---
diff --git a/data/theme/Adwaita/gnome-flashback-dark.css b/data/theme/Adwaita/gnome-flashback-dark.css
index faba4dc..0488183 100644
--- a/data/theme/Adwaita/gnome-flashback-dark.css
+++ b/data/theme/Adwaita/gnome-flashback-dark.css
@@ -54,3 +54,6 @@ gf-popup-window.solid {
 
 #gf-osd-window {
 }
+
+#gf-bubble {
+}
diff --git a/data/theme/Adwaita/gnome-flashback.css b/data/theme/Adwaita/gnome-flashback.css
index e79fb2f..6eda9ee 100644
--- a/data/theme/Adwaita/gnome-flashback.css
+++ b/data/theme/Adwaita/gnome-flashback.css
@@ -54,3 +54,6 @@ gf-popup-window.solid {
 
 #gf-osd-window {
 }
+
+#gf-bubble {
+}
diff --git a/data/theme/HighContrast/gnome-flashback.css b/data/theme/HighContrast/gnome-flashback.css
index 7af36e0..e32fb7b 100644
--- a/data/theme/HighContrast/gnome-flashback.css
+++ b/data/theme/HighContrast/gnome-flashback.css
@@ -54,3 +54,6 @@ gf-popup-window.solid {
 
 #gf-osd-window {
 }
+
+#gf-bubble {
+}
diff --git a/gnome-flashback/libnotifications/Makefile.am b/gnome-flashback/libnotifications/Makefile.am
index cb7ff5f..3b981ca 100644
--- a/gnome-flashback/libnotifications/Makefile.am
+++ b/gnome-flashback/libnotifications/Makefile.am
@@ -5,6 +5,8 @@ noinst_LTLIBRARIES = \
        $(NULL)
 
 libnotifications_la_CPPFLAGS = \
+       -I$(srcdir)/../../gnome-flashback \
+       -I$(top_builddir)/gnome-flashback \
        -I$(top_builddir)/gnome-flashback/libnotifications \
        $(NULL)
 
@@ -15,10 +17,10 @@ libnotifications_la_CFLAGS = \
        $(NULL)
 
 libnotifications_la_SOURCES = \
+       gf-bubble.c \
+       gf-bubble.h \
        gf-notifications.c \
        gf-notifications.h \
-       nd-bubble.c \
-       nd-bubble.h \
        nd-daemon.c \
        nd-daemon.h \
        nd-notification.c \
@@ -38,6 +40,7 @@ libnotifications_la_LDFLAGS = \
        $(NULL)
 
 libnotifications_la_LIBADD = \
+       $(top_builddir)/gnome-flashback/libcommon/libcommon.la \
        $(NOTIFICATIONS_LIBS) \
        $(NULL)
 
diff --git a/gnome-flashback/libnotifications/gf-bubble.c b/gnome-flashback/libnotifications/gf-bubble.c
new file mode 100644
index 0000000..ce74fd1
--- /dev/null
+++ b/gnome-flashback/libnotifications/gf-bubble.c
@@ -0,0 +1,687 @@
+/*
+ * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <strings.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "gf-bubble.h"
+#include "nd-notification.h"
+
+#define EXPIRATION_TIME_DEFAULT -1
+#define EXPIRATION_TIME_NEVER_EXPIRES 0
+#define TIMEOUT_SEC   5
+#define WIDTH         400
+#define IMAGE_SIZE    48
+#define BODY_X_OFFSET (IMAGE_SIZE + 8)
+
+typedef struct
+{
+  NdNotification *notification;
+
+  GtkWidget      *icon;
+  GtkWidget      *content_hbox;
+  GtkWidget      *summary_label;
+  GtkWidget      *close_button;
+  GtkWidget      *body_label;
+  GtkWidget      *actions_box;
+
+  gboolean        url_clicked_lock;
+
+  guint           timeout_id;
+} GfBubblePrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GfBubble, gf_bubble, GF_TYPE_POPUP_WINDOW)
+
+static void
+close_button_clicked_cb (GtkButton *button,
+                         GfBubble  *bubble)
+{
+  GfBubblePrivate *priv;
+
+  priv = gf_bubble_get_instance_private (bubble);
+
+  nd_notification_close (priv->notification, ND_NOTIFICATION_CLOSED_USER);
+  gtk_widget_destroy (GTK_WIDGET (bubble));
+}
+
+static gboolean
+activate_link_cb (GtkLabel *label,
+                  gchar    *uri,
+                  GfBubble *bubble)
+{
+  GfBubblePrivate *priv;
+  gchar *escaped_uri;
+  gchar *found;
+  gchar *cmd;
+
+  priv = gf_bubble_get_instance_private (bubble);
+
+  priv->url_clicked_lock = TRUE;
+
+  escaped_uri = g_shell_quote (uri);
+  found = NULL;
+  cmd = NULL;
+
+  if ((found = g_find_program_in_path ("gvfs-open")) != NULL)
+    cmd = g_strdup_printf ("gvfs-open %s", escaped_uri);
+  else if ((found = g_find_program_in_path ("xdg-open")) != NULL)
+    cmd = g_strdup_printf ("xdg-open %s", escaped_uri);
+  else if ((found = g_find_program_in_path ("firefox")) != NULL)
+    cmd = g_strdup_printf ("firefox %s", escaped_uri);
+  else
+    g_warning ("Unable to find a browser.");
+
+  g_free (escaped_uri);
+  g_free (found);
+
+  if (cmd != NULL)
+    {
+      g_spawn_command_line_async (cmd, NULL);
+      g_free (cmd);
+    }
+
+  return TRUE;
+}
+
+static void
+button_release_event_cb (GtkButton      *button,
+                         GdkEventButton *event,
+                         GfBubble       *bubble)
+{
+  GfBubblePrivate *priv;
+  const gchar *key;
+  gboolean transient;
+  gboolean resident;
+
+  priv = gf_bubble_get_instance_private (bubble);
+
+  key = g_object_get_data (G_OBJECT (button), "_action_key");
+  nd_notification_action_invoked (priv->notification, key);
+
+  transient = nd_notification_get_is_transient (priv->notification);
+  resident = nd_notification_get_is_resident (priv->notification);
+
+  if (transient || !resident)
+    gtk_widget_destroy (GTK_WIDGET (bubble));
+}
+
+static void
+add_notification_action (GfBubble    *bubble,
+                         const gchar *text,
+                         const gchar *key)
+{
+  GfBubblePrivate *priv;
+  GtkWidget *button;
+  GtkWidget *hbox;
+  GdkPixbuf *pixbuf;
+
+  priv = gf_bubble_get_instance_private (bubble);
+
+  button = gtk_button_new ();
+  gtk_box_pack_start (GTK_BOX (priv->actions_box), button, FALSE, FALSE, 0);
+  gtk_widget_show (button);
+
+  gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+  gtk_container_set_border_width (GTK_CONTAINER (button), 0);
+
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+  gtk_container_add (GTK_CONTAINER (button), hbox);
+  gtk_widget_show (hbox);
+
+  pixbuf = NULL;
+  if (nd_notification_get_action_icons (priv->notification))
+    pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), key, 20,
+                                       GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
+
+  if (pixbuf != NULL)
+    {
+      GtkWidget *image;
+      AtkObject *atkobj;
+
+      image = gtk_image_new_from_pixbuf (pixbuf);
+      gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
+      gtk_widget_show (image);
+
+      gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
+      gtk_widget_set_valign (image, GTK_ALIGN_CENTER);
+
+      atkobj = gtk_widget_get_accessible (GTK_WIDGET (button));
+      atk_object_set_name (atkobj, text);
+
+      g_object_unref (pixbuf);
+    }
+  else
+    {
+      GtkWidget *label;
+      gchar *buf;
+
+      label = gtk_label_new (NULL);
+      gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+      gtk_widget_show (label);
+
+      gtk_label_set_xalign (GTK_LABEL (label), 0.0);
+
+      buf = g_strdup_printf ("<small>%s</small>", text);
+      gtk_label_set_markup (GTK_LABEL (label), buf);
+      g_free (buf);
+    }
+
+  g_object_set_data_full (G_OBJECT (button), "_action_key",
+                          g_strdup (key), g_free);
+
+  g_signal_connect (button, "button-release-event",
+                    G_CALLBACK (button_release_event_cb), bubble);
+
+  gtk_widget_show (priv->actions_box);
+}
+
+static GdkPixbuf *
+scale_pixbuf (GdkPixbuf *pixbuf,
+              gint       max_width,
+              gint       max_height)
+{
+  gint pw;
+  gint ph;
+  gfloat scale_factor_x;
+  gfloat scale_factor_y;
+  gfloat scale_factor;
+
+  pw = gdk_pixbuf_get_width (pixbuf);
+  ph = gdk_pixbuf_get_height (pixbuf);
+
+  /* Determine which dimension requires the smallest scale. */
+  scale_factor_x = (gfloat) max_width / (gfloat) pw;
+  scale_factor_y = (gfloat) max_height / (gfloat) ph;
+
+  scale_factor = scale_factor_x;
+  if (scale_factor_x > scale_factor_y)
+    scale_factor = scale_factor_y;
+
+  if (scale_factor < 1.0)
+    {
+      gint scale_x;
+      gint scale_y;
+
+      scale_x = (gint) (pw * scale_factor);
+      scale_y = (gint) (ph * scale_factor);
+
+      return gdk_pixbuf_scale_simple (pixbuf, scale_x, scale_y,
+                                      GDK_INTERP_BILINEAR);
+    }
+
+  return g_object_ref (pixbuf);
+}
+
+static gboolean
+timeout_bubble (gpointer user_data)
+{
+  GfBubble *bubble;
+  GfBubblePrivate *priv;
+
+  bubble = GF_BUBBLE (user_data);
+  priv = gf_bubble_get_instance_private (bubble);
+
+  gtk_widget_destroy (GTK_WIDGET (bubble));
+
+  priv->timeout_id = 0;
+  return G_SOURCE_REMOVE;
+}
+
+static void
+add_timeout (GfBubble *bubble)
+{
+  GfBubblePrivate *priv;
+  gint timeout;
+
+  priv = gf_bubble_get_instance_private (bubble);
+
+  if (priv->timeout_id != 0)
+    {
+      g_source_remove (priv->timeout_id);
+      priv->timeout_id = 0;
+    }
+
+  timeout = nd_notification_get_timeout (priv->notification);
+
+  if (timeout == EXPIRATION_TIME_NEVER_EXPIRES)
+    return;
+
+  if (timeout == EXPIRATION_TIME_DEFAULT)
+    timeout = TIMEOUT_SEC * 1000;
+
+  priv->timeout_id = g_timeout_add (timeout, timeout_bubble, bubble);
+}
+
+static void
+update_bubble (GfBubble *bubble)
+{
+  GfBubblePrivate *priv;
+  const gchar *summary;
+  const gchar *body;
+  gchar *quoted;
+  gchar *str;
+  gboolean have_body;
+  gchar **actions;
+  gint i;
+  gboolean have_actions;
+  GdkPixbuf *pixbuf;
+  gboolean have_icon;
+
+  priv = gf_bubble_get_instance_private (bubble);
+
+  gtk_widget_show_all (GTK_WIDGET (bubble));
+
+  /* Summary label */
+
+  summary = nd_notification_get_summary (priv->notification);
+
+  quoted = g_markup_escape_text (summary, -1);
+  str = g_strdup_printf ("<b><big>%s</big></b>", quoted);
+  g_free (quoted);
+
+  gtk_label_set_markup (GTK_LABEL (priv->summary_label), str);
+  g_free (str);
+
+  /* Body label */
+
+  body = nd_notification_get_body (priv->notification);
+
+  if (pango_parse_markup (body, -1, 0, NULL, NULL, NULL, NULL))
+    {
+      gtk_label_set_markup (GTK_LABEL (priv->body_label), body);
+    }
+  else
+    {
+      str = g_markup_escape_text (body, -1);
+
+      gtk_label_set_text (GTK_LABEL (priv->body_label), str);
+      g_free (str);
+    }
+
+  have_body = body && *body != '\0';
+  gtk_widget_set_visible (priv->body_label, have_body);
+
+  /* Actions */
+
+  have_actions = FALSE;
+  gtk_container_foreach (GTK_CONTAINER (priv->actions_box),
+                         (GtkCallback) gtk_widget_destroy, NULL);
+
+  actions = nd_notification_get_actions (priv->notification);
+
+  for (i = 0; actions[i] != NULL; i += 2)
+    {
+      gchar *l;
+
+      l = actions[i + 1];
+
+      if (l == NULL)
+        {
+          g_warning ("Label not found for action - %s. The protocol specifies "
+                     "that a label must follow an action in the actions array",
+                     actions[i]);
+        }
+      else if (strcasecmp (actions[i], "default") != 0)
+        {
+          have_actions = TRUE;
+
+          add_notification_action (bubble, l, actions[i]);
+        }
+    }
+
+  gtk_widget_set_visible (priv->actions_box, have_actions);
+
+  /* Icon */
+
+  pixbuf = nd_notification_load_image (priv->notification, IMAGE_SIZE);
+
+  if (pixbuf != NULL)
+    {
+      GdkPixbuf *scaled;
+
+      scaled = scale_pixbuf (pixbuf, IMAGE_SIZE, IMAGE_SIZE);
+      g_object_unref (pixbuf);
+
+      gtk_image_set_from_pixbuf (GTK_IMAGE (priv->icon), scaled);
+
+      have_icon = scaled != NULL;
+      gtk_widget_set_visible (priv->icon, have_icon);
+
+      if (scaled != NULL)
+        {
+          gint width;
+
+          width = gdk_pixbuf_get_width (scaled);
+          g_object_unref (scaled);
+
+          width = MAX (BODY_X_OFFSET, width);
+
+          gtk_widget_set_size_request (priv->icon, width, -1);
+        }
+      else
+        {
+          gtk_widget_set_size_request (priv->icon, BODY_X_OFFSET, -1);
+        }
+    }
+
+  if (have_body || have_actions || have_icon)
+    gtk_widget_show (priv->content_hbox);
+  else
+    gtk_widget_hide (priv->content_hbox);
+
+  add_timeout (bubble);
+}
+
+static void
+notification_changed_cb (NdNotification *notification,
+                         GfBubble       *bubble)
+{
+  update_bubble (bubble);
+}
+
+static void
+gf_bubble_dispose (GObject *object)
+{
+  GfBubble *bubble;
+  GfBubblePrivate *priv;
+
+  bubble = GF_BUBBLE (object);
+  priv = gf_bubble_get_instance_private (bubble);
+
+  if (priv->timeout_id != 0)
+    {
+      g_source_remove (priv->timeout_id);
+      priv->timeout_id = 0;
+    }
+
+  G_OBJECT_CLASS (gf_bubble_parent_class)->dispose (object);
+}
+
+static void
+gf_bubble_finalize (GObject *object)
+{
+  GfBubble *bubble;
+  GfBubblePrivate *priv;
+
+  bubble = GF_BUBBLE (object);
+  priv = gf_bubble_get_instance_private (bubble);
+
+  g_clear_object (&priv->notification);
+
+  G_OBJECT_CLASS (gf_bubble_parent_class)->finalize (object);
+}
+
+static gboolean
+gf_bubble_button_release_event (GtkWidget      *widget,
+                                GdkEventButton *event)
+{
+  GfBubble *bubble;
+  GfBubblePrivate *priv;
+  gboolean retval;
+
+  bubble = GF_BUBBLE (widget);
+  priv = gf_bubble_get_instance_private (bubble);
+
+  retval = GTK_WIDGET_CLASS (gf_bubble_parent_class)->button_release_event (widget,
+                                                                            event);
+
+  if (priv->url_clicked_lock)
+    {
+      priv->url_clicked_lock = FALSE;
+      return retval;
+    }
+
+  nd_notification_action_invoked (priv->notification, "default");
+  gtk_widget_destroy (widget);
+
+  return retval;
+}
+
+static void
+gf_bubble_get_preferred_width (GtkWidget *widget,
+                               gint      *min_width,
+                               gint      *nat_width)
+{
+  GTK_WIDGET_CLASS (gf_bubble_parent_class)->get_preferred_width (widget,
+                                                                  min_width,
+                                                                  nat_width);
+
+  *nat_width = WIDTH;
+}
+
+static gboolean
+gf_bubble_motion_notify_event (GtkWidget      *widget,
+                               GdkEventMotion *event)
+{
+  GfBubble *bubble;
+  gboolean retval;
+
+  bubble = GF_BUBBLE (widget);
+
+  retval = GTK_WIDGET_CLASS (gf_bubble_parent_class)->motion_notify_event (widget,
+                                                                           event);
+
+  add_timeout (bubble);
+
+  return retval;
+}
+
+static void
+gf_bubble_realize (GtkWidget *widget)
+{
+  GfBubble *bubble;
+
+  bubble = GF_BUBBLE (widget);
+
+  GTK_WIDGET_CLASS (gf_bubble_parent_class)->realize (widget);
+
+  add_timeout (bubble);
+}
+
+static void
+gf_bubble_class_init (GfBubbleClass *bubble_class)
+{
+  GObjectClass *object_class;
+  GtkWidgetClass *widget_class;
+
+  object_class = G_OBJECT_CLASS (bubble_class);
+  widget_class = GTK_WIDGET_CLASS (bubble_class);
+
+  object_class->dispose = gf_bubble_dispose;
+  object_class->finalize = gf_bubble_finalize;
+
+  widget_class->button_release_event = gf_bubble_button_release_event;
+  widget_class->get_preferred_width = gf_bubble_get_preferred_width;
+  widget_class->motion_notify_event = gf_bubble_motion_notify_event;
+  widget_class->realize = gf_bubble_realize;
+}
+
+static void
+gf_bubble_init (GfBubble *bubble)
+{
+  GfBubblePrivate *priv;
+  GtkWidget *widget;
+  AtkObject *atkobj;
+  gint events;
+  GtkWidget *main_vbox;
+  GtkWidget *main_hbox;
+  GtkWidget *vbox;
+  GtkWidget *image;
+
+  priv = gf_bubble_get_instance_private (bubble);
+
+  widget = GTK_WIDGET (bubble);
+  atkobj = gtk_widget_get_accessible (widget);
+
+  atk_object_set_role (atkobj, ATK_ROLE_ALERT);
+
+  events = GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+           GDK_POINTER_MOTION_MASK;
+
+  gtk_widget_add_events (widget, events);
+  gtk_widget_set_name (widget, "gf-bubble");
+
+  /* Main vbox */
+
+  main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+  gtk_container_add (GTK_CONTAINER (bubble), main_vbox);
+  gtk_widget_show (main_vbox);
+
+  gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
+
+  /* Main hbox */
+
+  main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  gtk_box_pack_start (GTK_BOX (main_vbox), main_hbox, FALSE, FALSE, 0);
+  gtk_widget_show (main_hbox);
+
+  /* Icon */
+
+  priv->icon = gtk_image_new ();
+  gtk_box_pack_start (GTK_BOX (main_hbox), priv->icon, FALSE, FALSE, 0);
+  gtk_widget_show (priv->icon);
+
+  gtk_widget_set_margin_top (priv->icon, 5);
+  gtk_widget_set_size_request (priv->icon, BODY_X_OFFSET, -1);
+  gtk_widget_set_valign (priv->icon, GTK_ALIGN_START);
+
+  /* Vbox */
+
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+  gtk_box_pack_start (GTK_BOX (main_hbox), vbox, TRUE, TRUE, 0);
+  gtk_widget_show (vbox);
+
+  gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
+
+  /* Close button */
+
+  priv->close_button = gtk_button_new ();
+  gtk_box_pack_start (GTK_BOX (main_hbox), priv->close_button, FALSE, FALSE, 0);
+  gtk_widget_show (priv->close_button);
+
+  gtk_button_set_relief (GTK_BUTTON (priv->close_button), GTK_RELIEF_NONE);
+  gtk_widget_set_valign (priv->close_button, GTK_ALIGN_START);
+
+  g_signal_connect (priv->close_button, "clicked",
+                    G_CALLBACK (close_button_clicked_cb), bubble);
+
+  atkobj = gtk_widget_get_accessible (priv->close_button);
+  atk_object_set_description (atkobj, _("Closes the notification."));
+  atk_object_set_name (atkobj, "");
+
+  atk_action_set_description (ATK_ACTION (atkobj), 0,
+                              _("Closes the notification."));
+
+  image = gtk_image_new_from_icon_name ("window-close", GTK_ICON_SIZE_MENU);
+  gtk_container_add (GTK_CONTAINER (priv->close_button), image);
+  gtk_widget_show (image);
+
+  /* Summary label */
+
+  priv->summary_label = gtk_label_new (NULL);
+  gtk_box_pack_start (GTK_BOX (vbox), priv->summary_label, TRUE, TRUE, 0);
+  gtk_widget_show (priv->summary_label);
+
+  gtk_label_set_line_wrap (GTK_LABEL (priv->summary_label), TRUE);
+  gtk_label_set_line_wrap_mode (GTK_LABEL (priv->summary_label),
+                                PANGO_WRAP_WORD_CHAR);
+
+  gtk_label_set_xalign (GTK_LABEL (priv->summary_label), 0.0);
+  gtk_label_set_yalign (GTK_LABEL (priv->summary_label), 0.0);
+
+  atkobj = gtk_widget_get_accessible (priv->summary_label);
+  atk_object_set_description (atkobj, _("Notification summary text."));
+
+  /* Content hbox */
+
+  priv->content_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+  gtk_box_pack_start (GTK_BOX (vbox), priv->content_hbox, FALSE, FALSE, 0);
+  gtk_widget_show (priv->content_hbox);
+
+  /* Vbox */
+
+  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+  gtk_box_pack_start (GTK_BOX (priv->content_hbox), vbox, TRUE, TRUE, 0);
+  gtk_widget_show (vbox);
+
+  /* Body label */
+
+  priv->body_label = gtk_label_new (NULL);
+  gtk_box_pack_start (GTK_BOX (vbox), priv->body_label, TRUE, TRUE, 0);
+  gtk_widget_show (priv->body_label);
+
+  gtk_label_set_line_wrap (GTK_LABEL (priv->body_label), TRUE);
+  gtk_label_set_line_wrap_mode (GTK_LABEL (priv->body_label),
+                                PANGO_WRAP_WORD_CHAR);
+
+  gtk_label_set_xalign (GTK_LABEL (priv->body_label), 0.0);
+  gtk_label_set_yalign (GTK_LABEL (priv->body_label), 0.0);
+
+  g_signal_connect (priv->body_label, "activate-link",
+                    G_CALLBACK (activate_link_cb), bubble);
+
+  atkobj = gtk_widget_get_accessible (priv->body_label);
+  atk_object_set_description (atkobj, _("Notification summary text."));
+
+  /* Actions box */
+
+  priv->actions_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+  gtk_box_pack_start (GTK_BOX (vbox), priv->actions_box, FALSE, TRUE, 0);
+  gtk_widget_show (priv->actions_box);
+
+  gtk_widget_set_halign (priv->actions_box, GTK_ALIGN_END);
+}
+
+GfBubble *
+gf_bubble_new_for_notification (NdNotification *notification)
+{
+  GfBubble *bubble;
+  GfBubblePrivate *priv;
+
+  bubble = g_object_new (GF_TYPE_BUBBLE,
+                         "resizable", FALSE,
+                         "title", _("Notification"),
+                         NULL);
+
+  priv = gf_bubble_get_instance_private (bubble);
+
+  priv->notification = g_object_ref (notification);
+
+  g_signal_connect (notification, "changed",
+                    G_CALLBACK (notification_changed_cb), bubble);
+
+  update_bubble (bubble);
+
+  return bubble;
+}
+
+NdNotification *
+gf_bubble_get_notification (GfBubble *bubble)
+{
+  GfBubblePrivate *priv;
+
+  g_return_val_if_fail (GF_IS_BUBBLE (bubble), NULL);
+
+  priv = gf_bubble_get_instance_private (bubble);
+
+  return priv->notification;
+}
diff --git a/gnome-flashback/libnotifications/gf-bubble.h b/gnome-flashback/libnotifications/gf-bubble.h
new file mode 100644
index 0000000..a8273d7
--- /dev/null
+++ b/gnome-flashback/libnotifications/gf-bubble.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright (C) 2016 Alberts Muktupāvels
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GF_BUBBLE_H
+#define GF_BUBBLE_H
+
+#include <gtk/gtk.h>
+#include <libcommon/gf-popup-window.h>
+
+#include "nd-notification.h"
+
+G_BEGIN_DECLS
+
+#define GF_TYPE_BUBBLE gf_bubble_get_type ()
+G_DECLARE_DERIVABLE_TYPE (GfBubble, gf_bubble, GF, BUBBLE, GfPopupWindow)
+
+struct _GfBubbleClass
+{
+  GfPopupWindowClass parent_class;
+
+  void (* changed) (GfBubble *bubble);
+};
+
+GfBubble       *gf_bubble_new_for_notification (NdNotification *notification);
+
+NdNotification *gf_bubble_get_notification     (GfBubble       *bubble);
+
+G_END_DECLS
+
+#endif
diff --git a/gnome-flashback/libnotifications/nd-queue.c b/gnome-flashback/libnotifications/nd-queue.c
index 8e3e3ee..3c5a44c 100644
--- a/gnome-flashback/libnotifications/nd-queue.c
+++ b/gnome-flashback/libnotifications/nd-queue.c
@@ -568,13 +568,13 @@ get_stack_with_pointer (NdQueue *queue)
 }
 
 static void
-on_bubble_destroyed (NdBubble *bubble,
+on_bubble_destroyed (GfBubble *bubble,
                      NdQueue  *queue)
 {
         NdNotification *notification;
 
         g_debug ("Bubble destroyed");
-        notification = nd_bubble_get_notification (bubble);
+        notification = gf_bubble_get_notification (bubble);
 
         nd_notification_set_is_queued (notification, FALSE);
 
@@ -591,7 +591,7 @@ maybe_show_notification (NdQueue *queue)
 {
         gpointer        id;
         NdNotification *notification;
-        NdBubble       *bubble;
+        GfBubble       *bubble;
         NdStack        *stack;
         GList          *list;
 
@@ -621,7 +621,7 @@ maybe_show_notification (NdQueue *queue)
         notification = g_hash_table_lookup (queue->priv->notifications, id);
         g_assert (notification != NULL);
 
-        bubble = nd_bubble_new_for_notification (notification);
+        bubble = gf_bubble_new_for_notification (notification);
         g_signal_connect (bubble, "destroy", G_CALLBACK (on_bubble_destroyed), queue);
 
         nd_stack_add_bubble (stack, bubble, TRUE);
diff --git a/gnome-flashback/libnotifications/nd-stack.c b/gnome-flashback/libnotifications/nd-stack.c
index 335eca7..4ebfbf2 100644
--- a/gnome-flashback/libnotifications/nd-stack.c
+++ b/gnome-flashback/libnotifications/nd-stack.c
@@ -310,7 +310,7 @@ add_padding_to_rect (GdkRectangle *rect)
 
 static void
 nd_stack_shift_notifications (NdStack     *stack,
-                              NdBubble    *bubble,
+                              GfBubble    *bubble,
                               GList      **nw_l,
                               gint         init_width,
                               gint         init_height,
@@ -353,7 +353,7 @@ nd_stack_shift_notifications (NdStack     *stack,
                 *nw_y = y;
 
         for (i = 0, l = stack->priv->bubbles; l != NULL; i++, l = l->next) {
-                NdBubble       *nw2 = ND_BUBBLE (l->data);
+                GfBubble       *nw2 = GF_BUBBLE (l->data);
                 GtkRequisition  req;
 
                 if (bubble == NULL || nw2 != bubble) {
@@ -379,7 +379,7 @@ nd_stack_shift_notifications (NdStack     *stack,
         /* move bubbles at the bottom of the stack first
            to avoid overlapping */
         for (i = n_wins - 1, l = g_list_last (stack->priv->bubbles); l != NULL; i--, l = l->prev) {
-                NdBubble *nw2 = ND_BUBBLE (l->data);
+                GfBubble *nw2 = GF_BUBBLE (l->data);
 
                 if (bubble == NULL || nw2 != bubble) {
                         gtk_window_move (GTK_WINDOW (nw2), positions[i].x, positions[i].y);
@@ -422,7 +422,7 @@ nd_stack_queue_update_position (NdStack *stack)
 
 void
 nd_stack_add_bubble (NdStack  *stack,
-                     NdBubble *bubble,
+                     GfBubble *bubble,
                      gboolean  new_notification)
 {
         GtkRequisition  req;
@@ -450,7 +450,7 @@ nd_stack_add_bubble (NdStack  *stack,
 
 void
 nd_stack_remove_bubble (NdStack  *stack,
-                        NdBubble *bubble)
+                        GfBubble *bubble)
 {
         GList *remove_l = NULL;
 
diff --git a/gnome-flashback/libnotifications/nd-stack.h b/gnome-flashback/libnotifications/nd-stack.h
index 8007009..0e2f59c 100644
--- a/gnome-flashback/libnotifications/nd-stack.h
+++ b/gnome-flashback/libnotifications/nd-stack.h
@@ -19,7 +19,7 @@
 #define __ND_STACK_H
 
 #include <gtk/gtk.h>
-#include "nd-bubble.h"
+#include "gf-bubble.h"
 
 G_BEGIN_DECLS
 
@@ -61,10 +61,10 @@ NdStack *       nd_stack_new                   (GdkScreen      *screen,
 void            nd_stack_set_location          (NdStack        *stack,
                                                 NdStackLocation location);
 void            nd_stack_add_bubble            (NdStack        *stack,
-                                                NdBubble       *bubble,
+                                                GfBubble       *bubble,
                                                 gboolean        new_notification);
 void            nd_stack_remove_bubble         (NdStack        *stack,
-                                                NdBubble       *bubble);
+                                                GfBubble       *bubble);
 void            nd_stack_remove_all            (NdStack        *stack);
 GList *         nd_stack_get_bubbles           (NdStack        *stack);
 void            nd_stack_queue_update_position (NdStack        *stack);
diff --git a/po/POTFILES.in b/po/POTFILES.in
index d856c67..692387b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -18,7 +18,7 @@ gnome-flashback/libdisplay-config/flashback-display-config.c
 gnome-flashback/libend-session-dialog/gf-inhibit-dialog.c
 gnome-flashback/libend-session-dialog/gf-inhibit-dialog.ui
 gnome-flashback/libinput-sources/gf-input-sources.c
-gnome-flashback/libnotifications/nd-bubble.c
+gnome-flashback/libnotifications/gf-bubble.c
 gnome-flashback/libnotifications/nd-daemon.c
 gnome-flashback/libnotifications/nd-notification-box.c
 gnome-flashback/libnotifications/nd-queue.c


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]