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 e25f1ad9..ee910a12 100644
--- a/src/util/gtk-utils.cpp
+++ b/src/util/gtk-utils.cpp
@@ -1,3 +1,4 @@
+#include "glibmm/markup.h"
#include "glibmm/ustring.h"
#include
#include
@@ -180,3 +181,34 @@ void load_custom_icons(std::string section_name)
}
}
}
+
+/*
+ * 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))
+ {
+ 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 3b73e972..4c584a37 100644
--- a/src/util/gtk-utils.hpp
+++ b/src/util/gtk-utils.hpp
@@ -12,6 +12,9 @@ Glib::RefPtr load_icon_pixbuf_safe(std::string icon_path, int size)
/* Loads a CssProvider from the given path to the file, returns null if unsuccessful*/
Glib::RefPtr load_css_from_path(std::string path);
+bool is_markup(std::string);
+std::string markup_escape(std::string);
+
struct WfIconLoadOptions
{
int user_scale = -1;