diff --git a/src/panel/widgets/notifications/single-notification.cpp b/src/panel/widgets/notifications/single-notification.cpp
index 4e3fd5d5..e4b5453d 100644
--- a/src/panel/widgets/notifications/single-notification.cpp
+++ b/src/panel/widgets/notifications/single-notification.cpp
@@ -116,11 +116,12 @@ WfSingleNotification::WfSingleNotification(const Notification & notification)
text.set_wrap_mode(Pango::WrapMode::CHAR);
if (notification.body.empty())
{
- text.set_markup(notification.summary);
+ text.set_markup(markup_escape(notification.summary));
} else
{
// NOTE: that is not a really right way to implement FDN markup feature, but the easiest one.
- text.set_markup("" + notification.summary + "" + "\n" + notification.body);
+ text.set_markup("" + markup_escape(
+ notification.summary) + "" + "\n" + markup_escape(notification.body));
}
content.append(text);
diff --git a/src/panel/widgets/tray/item.cpp b/src/panel/widgets/tray/item.cpp
index fae84034..4b02ef99 100644
--- a/src/panel/widgets/tray/item.cpp
+++ b/src/panel/widgets/tray/item.cpp
@@ -167,10 +167,11 @@ void StatusNotifierItem::setup_tooltip()
get_item_property>("ToolTip");
auto tooltip_label_text = !tooltip_text.empty() && !tooltip_title.empty() ?
- "" + tooltip_title + ": " + tooltip_text :
- !tooltip_title.empty() ? tooltip_title :
- !tooltip_text.empty() ? tooltip_text :
- get_item_property("Title");
+ "" + markup_escape(tooltip_title) + ": " +
+ markup_escape(tooltip_text) :
+ !tooltip_title.empty() ? markup_escape(tooltip_title) :
+ !tooltip_text.empty() ? markup_escape(tooltip_text) :
+ markup_escape(get_item_property("Title"));
const auto pixbuf = extract_pixbuf(std::move(tooltip_icon_data));
bool icon_shown = false;
diff --git a/src/util/gtk-utils.cpp b/src/util/gtk-utils.cpp
index 80cec7b5..4b1a0f0d 100644
--- a/src/util/gtk-utils.cpp
+++ b/src/util/gtk-utils.cpp
@@ -1,3 +1,4 @@
+#include "glibmm/markup.h"
#include
#include
#include
@@ -72,3 +73,35 @@ void image_set_icon(Gtk::Image *image, std::string path)
image->set_from_icon_name(path);
}
}
+
+/*
+ * Check if this string appears to be markup
+ *
+ * Does not check it is *valid* markup
+ */
+bool is_markup(std::string input)
+{
+ int count_left = std::count(input.begin(), input.end(), '<');
+ int count_right = std::count(input.begin(), input.end(), '>');
+ int count_amp = std::count(input.begin(), input.end(), '&');
+ int count_semi = std::count(input.begin(), input.end(), ';');
+
+ if ((count_left == count_right) && (count_amp == count_semi))
+ {
+ /* And they pair up */
+ return true;
+ }
+
+ return false;
+}
+
+/* Escape string if it doesn't appear to be markup */
+std::string markup_escape(std::string input)
+{
+ if (is_markup(input))
+ {
+ return input;
+ }
+
+ return Glib::Markup::escape_text(input);
+}
diff --git a/src/util/gtk-utils.hpp b/src/util/gtk-utils.hpp
index 8cac6c29..ef78616e 100644
--- a/src/util/gtk-utils.hpp
+++ b/src/util/gtk-utils.hpp
@@ -20,3 +20,7 @@ struct WfIconLoadOptions
void invert_pixbuf(Glib::RefPtr& pbuff);
void image_set_icon(Gtk::Image *image, std::string path);
+
+bool is_markup(std::string);
+
+std::string markup_escape(std::string);