summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--po/POTFILES.in1
-rw-r--r--src/common/fe.h1
-rw-r--r--src/common/outbound.c6
-rw-r--r--src/common/plugin.c20
-rw-r--r--src/common/plugin.h1
-rw-r--r--src/fe-gtk/Makefile.am12
-rw-r--r--src/fe-gtk/fe-gtk.c3
-rw-r--r--src/fe-gtk/fe-gtk.vcxproj9
-rw-r--r--src/fe-gtk/fe-gtk.vcxproj.filters11
-rw-r--r--src/fe-gtk/notifications/notification-backend.h27
-rw-r--r--src/fe-gtk/notifications/notification-dummy.c39
-rw-r--r--src/fe-gtk/notifications/notification-libnotify.c73
-rw-r--r--src/fe-gtk/notifications/notification-windows.c87
-rw-r--r--src/fe-gtk/notifications/notification-winrt.cpp100
-rw-r--r--src/fe-gtk/notifications/notifications-winrt.vcxproj127
-rw-r--r--src/fe-gtk/notifications/notifications-winrt.vcxproj.filters22
-rw-r--r--src/fe-gtk/plugin-notification.c225
-rw-r--r--src/fe-gtk/plugin-notification.h25
-rw-r--r--src/fe-gtk/plugin-tray.c107
-rw-r--r--src/fe-gtk/setup.c84
-rw-r--r--src/fe-text/fe-text.c1
-rw-r--r--win32/hexchat.exe.manifest (renamed from src/fe-gtk/hexchat.exe.manifest)12
-rw-r--r--win32/hexchat.props1
-rw-r--r--win32/hexchat.sln20
-rw-r--r--win32/installer/hexchat.iss.tt4
25 files changed, 871 insertions, 147 deletions
diff --git a/po/POTFILES.in b/po/POTFILES.in
index c2a5ede1..b274cda9 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -32,6 +32,7 @@ src/fe-gtk/joind.c
 src/fe-gtk/maingui.c
 src/fe-gtk/menu.c
 src/fe-gtk/notifygui.c
+src/fe-gtk/plugin-notifications.c
 src/fe-gtk/plugin-tray.c
 src/fe-gtk/plugingui.c
 src/fe-gtk/rawlog.c
diff --git a/src/common/fe.h b/src/common/fe.h
index 9d8919ac..a3bd2afa 100644
--- a/src/common/fe.h
+++ b/src/common/fe.h
@@ -178,7 +178,6 @@ typedef enum
 } feicon;
 void fe_tray_set_icon (feicon icon);
 void fe_tray_set_tooltip (const char *text);
-void fe_tray_set_balloon (const char *title, const char *text);
 void fe_open_chan_list (server *serv, char *filter, int do_refresh);
 const char *fe_get_default_font ();
 
diff --git a/src/common/outbound.c b/src/common/outbound.c
index 8884b41e..ed00aa19 100644
--- a/src/common/outbound.c
+++ b/src/common/outbound.c
@@ -3470,12 +3470,6 @@ cmd_topic (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 static int
 cmd_tray (struct session *sess, char *tbuf, char *word[], char *word_eol[])
 {
-	if (strcmp (word[2], "-b") == 0)
-	{
-		fe_tray_set_balloon (word[3], word[4][0] ? word[4] : NULL);
-		return TRUE;
-	}
-
 	if (strcmp (word[2], "-t") == 0)
 	{
 		fe_tray_set_tooltip (word[3][0] ? word[3] : NULL);
diff --git a/src/common/plugin.c b/src/common/plugin.c
index d2782e01..8d990dc9 100644
--- a/src/common/plugin.c
+++ b/src/common/plugin.c
@@ -355,15 +355,11 @@ plugin_kill_all (void)
 
 #ifdef USE_PLUGIN
 
-/* load a plugin from a filename. Returns: NULL-success or an error string */
-
-char *
-plugin_load (session *sess, char *filename, char *arg)
+GModule *
+module_load (char *filename)
 {
 	void *handle;
 	char *filepart;
-	hexchat_init_func *init_func;
-	hexchat_deinit_func *deinit_func;
 	char *pluginpath;
 
 	/* get the filename without path */
@@ -383,6 +379,18 @@ plugin_load (session *sess, char *filename, char *arg)
 		handle = g_module_open (filename, 0);
 	}
 
+	return handle;
+}
+
+/* load a plugin from a filename. Returns: NULL-success or an error string */
+
+char *
+plugin_load (session *sess, char *filename, char *arg)
+{
+	GModule *handle = module_load (filename);
+	hexchat_init_func *init_func;
+	hexchat_deinit_func *deinit_func;
+
 	if (handle == NULL)
 		return (char *)g_module_error ();
 
diff --git a/src/common/plugin.h b/src/common/plugin.h
index db0054cb..5743f39a 100644
--- a/src/common/plugin.h
+++ b/src/common/plugin.h
@@ -163,6 +163,7 @@ struct _hexchat_plugin
 };
 #endif
 
+GModule *module_load (char *filename);
 char *plugin_load (session *sess, char *filename, char *arg);
 int plugin_reload (session *sess, char *name, int by_filename);
 void plugin_add (session *sess, char *filename, void *handle, void *init_func, void *deinit_func, char *arg, int fake);
diff --git a/src/fe-gtk/Makefile.am b/src/fe-gtk/Makefile.am
index 78ca1e45..28c932b1 100644
--- a/src/fe-gtk/Makefile.am
+++ b/src/fe-gtk/Makefile.am
@@ -12,7 +12,7 @@ hexchat_LDADD = ../common/libhexchatcommon.a $(GUI_LIBS)
 EXTRA_DIST = \
 	ascii.h banlist.h chanlist.h chanview.h chanview-tabs.c \
 	chanview-tree.c custom-list.h editlist.h fe-gtk.h fkeys.h gtkutil.h joind.h \
-	maingui.h menu.h notifygui.h palette.h pixmaps.h \
+	maingui.h menu.h notifygui.h  notifications palette.h pixmaps.h plugin-notification.h \
 	plugin-tray.h plugingui.c plugingui.h rawlog.h sexy-iso-codes.h \
 	sexy-spell-entry.h textgui.h urlgrab.h userlistgui.h xtext.h \
 	../../data/hexchat.gresource.xml
@@ -29,10 +29,16 @@ if HAVE_ISO_CODES
 iso_codes_c = sexy-iso-codes.c
 endif
 
+if USE_LIBNOTIFY
+notify_c = notifications/notification-libnotify.c
+else
+notify_c = notifications/notification-dummy.c
+endif
+
 hexchat_SOURCES = ascii.c banlist.c chanlist.c chanview.c custom-list.c \
 	dccgui.c editlist.c fe-gtk.c fkeys.c gtkutil.c ignoregui.c joind.c menu.c \
-	maingui.c notifygui.c palette.c pixmaps.c plugin-tray.c $(plugingui_c) \
-	rawlog.c resources.c servlistgui.c setup.c $(iso_codes_c) \
+	maingui.c notifygui.c $(notify_c) palette.c pixmaps.c plugin-tray.c $(plugingui_c) \
+	plugin-notification.c rawlog.c resources.c servlistgui.c setup.c $(iso_codes_c) \
 	sexy-spell-entry.c textgui.c urlgrab.c userlistgui.c xtext.c
 hexchat_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/src/common
 
diff --git a/src/fe-gtk/fe-gtk.c b/src/fe-gtk/fe-gtk.c
index 21aa9b9b..8c163eb7 100644
--- a/src/fe-gtk/fe-gtk.c
+++ b/src/fe-gtk/fe-gtk.c
@@ -52,6 +52,7 @@
 #include "plugin-tray.h"
 #include "urlgrab.h"
 #include "setup.h"
+#include "plugin-notification.h"
 
 #ifdef USE_LIBCANBERRA
 #include <canberra.h>
@@ -381,6 +382,8 @@ fe_idle (gpointer data)
 {
 	session *sess = sess_list->data;
 
+	plugin_add (sess, NULL, NULL, notification_plugin_init, notification_plugin_deinit, NULL, FALSE);
+
 	plugin_add (sess, NULL, NULL, tray_plugin_init, tray_plugin_deinit, NULL, FALSE);
 
 	if (arg_minimize == 1)
diff --git a/src/fe-gtk/fe-gtk.vcxproj b/src/fe-gtk/fe-gtk.vcxproj
index 59ab17c6..62790283 100644
--- a/src/fe-gtk/fe-gtk.vcxproj
+++ b/src/fe-gtk/fe-gtk.vcxproj
@@ -60,7 +60,7 @@
       <FunctionLevelLinking>true</FunctionLevelLinking>

       <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(SolutionDir)..;$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories>$(SolutionDir)..;..\common;$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

       <MultiProcessorCompilation>true</MultiProcessorCompilation>

       <DisableSpecificWarnings>4244;%(DisableSpecificWarnings)</DisableSpecificWarnings>

     </ClCompile>

@@ -81,7 +81,7 @@
       <FunctionLevelLinking>true</FunctionLevelLinking>

       <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_WINDOWS;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>$(SolutionDir)..;$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories>$(SolutionDir)..;..\common;$(DepsRoot)\include;$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

       <MultiProcessorCompilation>true</MultiProcessorCompilation>

       <DisableSpecificWarnings>4244;4267;%(DisableSpecificWarnings)</DisableSpecificWarnings>

     </ClCompile>

@@ -120,6 +120,7 @@ powershell "Get-Content -Encoding UTF8 '$(SolutionDir)..\src\fe-gtk\hexchat.rc.u
     <ClInclude Include="joind.h" />

     <ClInclude Include="maingui.h" />

     <ClInclude Include="menu.h" />

+    <ClInclude Include="notifications\notification-backend.h" />

     <ClInclude Include="notifygui.h" />

     <ClInclude Include="palette.h" />

     <ClInclude Include="pixmaps.h" />

@@ -150,9 +151,11 @@ powershell "Get-Content -Encoding UTF8 '$(SolutionDir)..\src\fe-gtk\hexchat.rc.u
     <ClCompile Include="joind.c" />

     <ClCompile Include="maingui.c" />

     <ClCompile Include="menu.c" />

+    <ClCompile Include="notifications\notification-windows.c" />

     <ClCompile Include="notifygui.c" />

     <ClCompile Include="palette.c" />

     <ClCompile Include="pixmaps.c" />

+    <ClCompile Include="plugin-notification.c" />

     <ClCompile Include="plugin-tray.c" />

     <ClCompile Include="plugingui.c" />

     <ClCompile Include="rawlog.c" />

@@ -167,7 +170,7 @@ powershell "Get-Content -Encoding UTF8 '$(SolutionDir)..\src\fe-gtk\hexchat.rc.u
     <ClCompile Include="xtext.c" />

   </ItemGroup>

   <ItemGroup>

-    <Manifest Include="hexchat.exe.manifest" />

+    <Manifest Include="..\..\win32\hexchat.exe.manifest" />

   </ItemGroup>

   <ItemGroup>

     <None Include="hexchat.rc.tt" />

diff --git a/src/fe-gtk/fe-gtk.vcxproj.filters b/src/fe-gtk/fe-gtk.vcxproj.filters
index 4598b1f2..a950d02f 100644
--- a/src/fe-gtk/fe-gtk.vcxproj.filters
+++ b/src/fe-gtk/fe-gtk.vcxproj.filters
@@ -93,6 +93,9 @@
     <ClInclude Include="setup.h">

       <Filter>Header Files</Filter>

     </ClInclude>

+    <ClInclude Include="notifications\notification-backend.h">

+      <Filter>Header Files</Filter>

+    </ClInclude>

   </ItemGroup>

   <ItemGroup>

     <ClCompile Include="ascii.c">

@@ -182,9 +185,15 @@
     <ClCompile Include="resources.c">

       <Filter>Source Files</Filter>

     </ClCompile>

+    <ClCompile Include="plugin-notification.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="notifications\notification-windows.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

   </ItemGroup>

   <ItemGroup>

-    <Manifest Include="hexchat.exe.manifest">

+    <Manifest Include="..\..\win32\hexchat.exe.manifest">

       <Filter>Resource Files</Filter>

     </Manifest>

   </ItemGroup>

diff --git a/src/fe-gtk/notifications/notification-backend.h b/src/fe-gtk/notifications/notification-backend.h
new file mode 100644
index 00000000..98686d73
--- /dev/null
+++ b/src/fe-gtk/notifications/notification-backend.h
@@ -0,0 +1,27 @@
+/* HexChat
+ * Copyright (C) 2015 Patrick Griffis.
+ *
+ * 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 HEXCHAT_PLUGIN_NOTIFICATION_BACKEND_H
+#define HEXCHAT_PLUGIN_NOTIFICATION_BACKEND_H
+
+int notification_backend_supported (void);
+void notification_backend_show (const char *title, const char *text, int timeout);
+int notification_backend_init (void);
+void notification_backend_deinit (void);
+
+#endif
diff --git a/src/fe-gtk/notifications/notification-dummy.c b/src/fe-gtk/notifications/notification-dummy.c
new file mode 100644
index 00000000..1b719cfa
--- /dev/null
+++ b/src/fe-gtk/notifications/notification-dummy.c
@@ -0,0 +1,39 @@
+/* HexChat
+ * Copyright (C) 2015 Patrick Griffis.
+ *
+ * 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
+ */
+
+void
+notification_backend_show (const char *title, const char *text, int timeout)
+{
+}
+
+int
+notification_backend_init (void)
+{
+	return 0;
+}
+
+void
+notification_backend_deinit (void)
+{
+}
+
+int
+notification_backend_supported (void)
+{
+	return 0;
+}
diff --git a/src/fe-gtk/notifications/notification-libnotify.c b/src/fe-gtk/notifications/notification-libnotify.c
new file mode 100644
index 00000000..d3e3a992
--- /dev/null
+++ b/src/fe-gtk/notifications/notification-libnotify.c
@@ -0,0 +1,73 @@
+/* HexChat
+ * Copyright (C) 2015 Patrick Griffis.
+ *
+ * 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.h>
+#include <libnotify/notify.h>
+
+static gboolean strip_markup = FALSE;
+
+void
+notification_backend_show (const char *title, const char *text, int timeout)
+{
+	NotifyNotification *notification;
+
+	if (strip_markup)
+		text = g_markup_escape_text (text, -1);
+
+	notification = notify_notification_new (title, text, "hexchat");
+	notify_notification_set_hint (notification, "desktop-entry", g_variant_new_string ("hexchat"));
+
+	notify_notification_set_timeout (notification, timeout);
+	notify_notification_show (notification, NULL);
+
+	g_object_unref (notification);
+	if (strip_markup)
+		g_free ((char*)text);
+}
+
+int
+notification_backend_init (void)
+{
+	GList* server_caps;
+
+	if (!NOTIFY_CHECK_VERSION (0, 7, 0))
+		return 0;
+
+	if (!notify_init (PACKAGE_NAME))
+		return 0;
+
+	server_caps = notify_get_server_caps ();
+	if (g_list_find_custom (server_caps, "body-markup", (GCompareFunc)g_strcmp0))
+		strip_markup = TRUE;
+	g_list_free_full (server_caps, g_free);
+
+	return 1;
+}
+
+void
+notification_backend_deinit (void)
+{
+	notify_uninit ();
+}
+
+int
+notification_backend_supported (void)
+{
+	return notify_is_initted ();
+}
diff --git a/src/fe-gtk/notifications/notification-windows.c b/src/fe-gtk/notifications/notification-windows.c
new file mode 100644
index 00000000..16cf3412
--- /dev/null
+++ b/src/fe-gtk/notifications/notification-windows.c
@@ -0,0 +1,87 @@
+/* HexChat
+ * Copyright (C) 2015 Arnav Singh.
+ *
+ * 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 <gmodule.h>
+
+#include "hexchat.h"
+#include "plugin.h"
+
+#include <Windows.h>
+
+void (*winrt_notification_backend_show) (const char *title, const char *text, int timeout) = NULL;
+int (*winrt_notification_backend_init) (void) = NULL;
+void (*winrt_notification_backend_deinit) (void) = NULL;
+int (*winrt_notification_backend_supported) (void) = NULL;
+
+void
+notification_backend_show (const char *title, const char *text, int timeout)
+{
+	if (winrt_notification_backend_show == NULL)
+	{
+		return;
+	}
+
+	winrt_notification_backend_show (title, text, timeout);
+}
+
+int
+notification_backend_init (void)
+{
+	UINT original_error_mode;
+	GModule *module;
+
+	/* Temporarily suppress the "DLL could not be loaded" dialog box before trying to load hcnotifications-winrt.dll */
+	original_error_mode = GetErrorMode ();
+	SetErrorMode(SEM_FAILCRITICALERRORS);
+	module = module_load (HEXCHATLIBDIR "\\hcnotifications-winrt.dll");
+	SetErrorMode (original_error_mode);
+
+	if (module == NULL)
+	{
+		return 0;
+	}
+
+	g_module_symbol (module, "notification_backend_show", (gpointer *) &winrt_notification_backend_show);
+	g_module_symbol (module, "notification_backend_init", (gpointer *) &winrt_notification_backend_init);
+	g_module_symbol (module, "notification_backend_deinit", (gpointer *) &winrt_notification_backend_deinit);
+	g_module_symbol (module, "notification_backend_supported", (gpointer *) &winrt_notification_backend_supported);
+
+	return winrt_notification_backend_init ();
+}
+
+void
+notification_backend_deinit (void)
+{
+	if (winrt_notification_backend_deinit == NULL)
+	{
+		return;
+	}
+
+	winrt_notification_backend_deinit ();
+}
+
+int
+notification_backend_supported (void)
+{
+	if (winrt_notification_backend_supported == NULL)
+	{
+		return 0;
+	}
+
+	return winrt_notification_backend_supported ();
+}
diff --git a/src/fe-gtk/notifications/notification-winrt.cpp b/src/fe-gtk/notifications/notification-winrt.cpp
new file mode 100644
index 00000000..74cc2e78
--- /dev/null
+++ b/src/fe-gtk/notifications/notification-winrt.cpp
@@ -0,0 +1,100 @@
+/* HexChat
+ * Copyright (c) 2014 Leetsoftwerx
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <string>
+#include <codecvt>
+
+#include <roapi.h>
+#include <windows.ui.notifications.h>
+
+using namespace Windows::UI::Notifications;
+using namespace Windows::Data::Xml::Dom;
+
+static ToastNotifier ^ notifier = nullptr;
+
+static std::wstring
+widen(const std::string & to_widen)
+{
+	std::wstring_convert<std::codecvt_utf8_utf16<wchar_t> > converter;
+	return converter.from_bytes(to_widen);
+}
+
+extern "C"
+{
+	__declspec (dllexport) void
+	notification_backend_show (const char *title, const char *text, int timeout)
+	{
+		try
+		{
+			auto toastTemplate = ToastNotificationManager::GetTemplateContent (ToastTemplateType::ToastText02);
+			auto node_list = toastTemplate->GetElementsByTagName ("text");
+			UINT node_count = node_list->Length;
+
+			auto wtitle = widen (title);
+			node_list->GetAt (0)->AppendChild (
+				toastTemplate->CreateTextNode (Platform::StringReference (wtitle.c_str (), wtitle.size ())));
+
+			auto wtext = widen (text);
+			node_list->GetAt (1)->AppendChild (
+				toastTemplate->CreateTextNode (Platform::StringReference (wtext.c_str (), wtext.size ())));
+
+			// Mute sound, we already play our own
+			auto node = toastTemplate->SelectSingleNode ("/toast");
+			auto audio_elem = toastTemplate->CreateElement ("audio");
+			audio_elem->SetAttribute ("silent", "true");
+			static_cast<XmlElement^>(node)->AppendChild (audio_elem);
+
+			notifier->Show (ref new ToastNotification (toastTemplate));
+		}
+		catch (Platform::Exception ^ ex)
+		{
+		}
+		catch (...)
+		{
+		}
+	}
+
+	__declspec (dllexport) int
+	notification_backend_init (void)
+	{
+		if (!notifier)
+			notifier = ToastNotificationManager::CreateToastNotifier ("HexChat.Desktop.Notify");
+
+		if (FAILED (Windows::Foundation::Initialize (RO_INIT_SINGLETHREADED)))
+			return 0;
+
+		return 1;
+	}
+
+	__declspec (dllexport) 	void
+	notification_backend_deinit (void)
+	{
+		notifier = nullptr;
+		Windows::Foundation::Uninitialize ();
+	}
+
+	__declspec (dllexport) int
+	notification_backend_supported (void)
+	{
+		return 1;
+	}
+}
diff --git a/src/fe-gtk/notifications/notifications-winrt.vcxproj b/src/fe-gtk/notifications/notifications-winrt.vcxproj
new file mode 100644
index 00000000..7a4e9888
--- /dev/null
+++ b/src/fe-gtk/notifications/notifications-winrt.vcxproj
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8"?>

+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+  <ItemGroup Label="ProjectConfigurations">

+    <ProjectConfiguration Include="Release|Win32">

+      <Configuration>Release</Configuration>

+      <Platform>Win32</Platform>

+    </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|x64">

+      <Configuration>Release</Configuration>

+      <Platform>x64</Platform>

+    </ProjectConfiguration>

+  </ItemGroup>

+  <ItemGroup>

+    <ClCompile Include="notification-winrt.cpp">

+      <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</CompileAsWinRT>

+      <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</CompileAsWinRT>

+    </ClCompile>

+  </ItemGroup>

+  <PropertyGroup Label="Globals">

+    <ProjectGuid>{C53145CC-D021-40C9-B97C-0249AB9A43C9}</ProjectGuid>

+    <Keyword>Win32Proj</Keyword>

+    <RootNamespace>notifications-winrt</RootNamespace>

+    <ProjectName>notifications-winrt</ProjectName>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <PlatformToolset>v120</PlatformToolset>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

+    <UseDebugLibraries>false</UseDebugLibraries>

+    <WholeProgramOptimization>true</WholeProgramOptimization>

+    <CharacterSet>Unicode</CharacterSet>

+    <PlatformToolset>v120</PlatformToolset>

+  </PropertyGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

+  <ImportGroup Label="ExtensionSettings">

+  </ImportGroup>

+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="..\..\..\win32\hexchat.props" />

+  </ImportGroup>

+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

+    <Import Project="..\..\..\win32\hexchat.props" />

+  </ImportGroup>

+  <PropertyGroup Label="UserMacros" />

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <LinkIncremental>false</LinkIncremental>

+    <TargetName>hcnotifications-winrt</TargetName>

+    <OutDir>$(HexChatBin)</OutDir>

+    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

+    <IncludePath>$(IncludePath)</IncludePath>

+    <LibraryPath>$(LibraryPath)</LibraryPath>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <LinkIncremental>false</LinkIncremental>

+    <OutDir>$(HexChatBin)</OutDir>

+    <TargetName>hcnotifications-winrt</TargetName>

+    <IntDir>$(HexChatObj)$(ProjectName)\</IntDir>

+    <IncludePath>$(IncludePath)</IncludePath>

+    <LibraryPath>$(LibraryPath)</LibraryPath>

+  </PropertyGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <PrecompiledHeader>NotUsing</PrecompiledHeader>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>WIN32;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_MEMORY;_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES_MEMORY;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT;NDEBUG;_WINDOWS;_USRDLL;NOTIFICATIONS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <SDLCheck>true</SDLCheck>

+      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <PrecompiledHeaderFile />

+      <AdditionalUsingDirectories>$(VCInstallDir)vcpackages;$(FrameworkSdkDir)References\CommonConfiguration\Neutral;%(AdditionalUsingDirectories)</AdditionalUsingDirectories>

+      <WholeProgramOptimization>true</WholeProgramOptimization>

+    </ClCompile>

+    <Link>

+      <SubSystem>Windows</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <LargeAddressAware>true</LargeAddressAware>

+      <FixedBaseAddress>false</FixedBaseAddress>

+      <ModuleDefinitionFile>

+      </ModuleDefinitionFile>

+      <AdditionalDependencies>$(DepLibs);mincore.lib;runtimeobject.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <MinimumRequiredVersion>6.03</MinimumRequiredVersion>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

+    <ClCompile>

+      <WarningLevel>Level3</WarningLevel>

+      <PrecompiledHeader>NotUsing</PrecompiledHeader>

+      <Optimization>MaxSpeed</Optimization>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+      <PreprocessorDefinitions>WIN32;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_MEMORY;_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES_MEMORY;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT;NDEBUG;_WINDOWS;_USRDLL;NOTIFICATIONS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <SDLCheck>true</SDLCheck>

+      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <PrecompiledHeaderFile />

+      <AdditionalUsingDirectories>$(VCInstallDir)vcpackages;$(FrameworkSdkDir)References\CommonConfiguration\Neutral;%(AdditionalUsingDirectories)</AdditionalUsingDirectories>

+      <WholeProgramOptimization>true</WholeProgramOptimization>

+    </ClCompile>

+    <Link>

+      <SubSystem>Windows</SubSystem>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <LargeAddressAware>true</LargeAddressAware>

+      <FixedBaseAddress>false</FixedBaseAddress>

+      <ModuleDefinitionFile>

+      </ModuleDefinitionFile>

+      <AdditionalDependencies>$(DepLibs);mincore.lib;runtimeobject.lib;%(AdditionalDependencies)</AdditionalDependencies>

+      <MinimumRequiredVersion>6.03</MinimumRequiredVersion>

+      <AdditionalLibraryDirectories>$(DepsRoot)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+    </Link>

+  </ItemDefinitionGroup>

+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

+  <ImportGroup Label="ExtensionTargets">

+  </ImportGroup>

+</Project>
\ No newline at end of file
diff --git a/src/fe-gtk/notifications/notifications-winrt.vcxproj.filters b/src/fe-gtk/notifications/notifications-winrt.vcxproj.filters
new file mode 100644
index 00000000..06f4e558
--- /dev/null
+++ b/src/fe-gtk/notifications/notifications-winrt.vcxproj.filters
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Source Files">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Header Files">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Resource Files">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="notification-winrt.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/src/fe-gtk/plugin-notification.c b/src/fe-gtk/plugin-notification.c
new file mode 100644
index 00000000..43ceeece
--- /dev/null
+++ b/src/fe-gtk/plugin-notification.c
@@ -0,0 +1,225 @@
+/* HexChat
+ * Copyright (C) 2015 Patrick Griffis.
+ *
+ * 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.h>
+
+#include "../common/hexchat-plugin.h"
+#include "../common/inbound.h" /* For alert_match_word() */
+#include "notifications/notification-backend.h"
+
+static hexchat_plugin *ph;
+
+static gboolean
+should_alert (void)
+{
+	int omit_away, omit_focused, omit_tray;
+
+	if (hexchat_get_prefs (ph, "gui_focus_omitalerts", NULL, &omit_focused) == 3 && omit_focused)
+	{
+		const char *status = hexchat_get_info (ph, "win_status");
+
+		if (status && !g_strcmp0 (status, "active"))
+			return FALSE;
+	}
+
+	if (hexchat_get_prefs (ph, "away_omit_alerts", NULL, &omit_away) == 3 && omit_away)
+	{
+		if (hexchat_get_info (ph, "away"))
+			return FALSE;
+	}
+
+	if (hexchat_get_prefs (ph, "gui_tray_quiet", NULL, &omit_tray) == 3 && omit_tray)
+	{
+		int tray_enabled;
+
+		if (hexchat_get_prefs (ph, "gui_tray", NULL, &tray_enabled) == 3 && tray_enabled)
+		{
+			const char *status = hexchat_get_info (ph, "win_status");
+
+			if (status && g_strcmp0 (status, "hidden") != 0)
+				return FALSE;
+		}
+	}
+
+	return TRUE;
+}
+
+/* Returns timeout in ms */
+static int
+get_timeout (void)
+{
+	int timeout = 0;
+	hexchat_get_prefs (ph, "input_balloon_time", NULL, &timeout);
+
+	return timeout * 1000;
+}
+
+static gboolean
+is_ignored (char *nick)
+{
+	const char *no_hilight;
+
+	if (hexchat_get_prefs (ph, "irc_no_hilight", &no_hilight, NULL) == 1 && no_hilight)
+	{
+		return alert_match_word (nick, (char*)no_hilight);
+	}
+	return FALSE;
+}
+
+static void
+show_notification (const char *title, const char *text)
+{
+	char *stripped_title, *stripped_text;
+
+	/* Strip all colors */
+	stripped_title = hexchat_strip (ph, title, -1, 7);
+	stripped_text = hexchat_strip (ph, text, -1, 7);
+	
+	notification_backend_show (stripped_title, stripped_text, get_timeout ());
+
+	hexchat_free (ph, stripped_title);
+	hexchat_free (ph, stripped_text);
+}
+
+static void
+show_notificationf (const char *text, const char *format, ...)
+{
+	va_list args;
+	char *buf;
+
+	va_start (args, format);
+	buf = g_strdup_vprintf (format, args);
+	va_end (args);
+
+	show_notification (buf, text);
+	g_free (buf);
+}
+
+static int
+incoming_hilight_cb (char *word[], gpointer userdata)
+{
+	int hilight;
+
+	if (hexchat_get_prefs (ph, "input_balloon_hilight", NULL, &hilight) == 3 && hilight && should_alert())
+	{
+		show_notificationf (word[2], _("Highlighted message from: %s (%s)"), word[1], hexchat_get_info (ph, "channel"));
+	}
+	return HEXCHAT_EAT_NONE;
+}
+
+static int
+incoming_message_cb (char *word[], gpointer userdata)
+{
+	int message;
+
+	if (hexchat_get_prefs (ph, "input_balloon_chans", NULL, &message) == 3 && message && should_alert ())
+	{
+		show_notificationf (word[2], _("Channel message from: %s (%s)"), word[1], hexchat_get_info (ph, "channel"));
+	}
+	return HEXCHAT_EAT_NONE;
+}
+
+static int
+incoming_priv_cb (char *word[], gpointer userdata)
+{
+	int priv;
+
+	if (hexchat_get_prefs (ph, "input_balloon_priv", NULL, &priv) == 3 && priv && should_alert ())
+	{
+		const char *network = hexchat_get_info (ph, "network");
+		if (!network)
+			network = hexchat_get_info (ph, "server");
+
+		if (userdata != NULL) /* Special event */
+		{
+			if (GPOINTER_TO_INT (userdata) == 3)
+			{
+				if (!is_ignored (word[2]))
+					show_notificationf (word[1], _("File offer from: %s (%s)"), word[2], network);
+			}
+			else if (GPOINTER_TO_INT (userdata) == 2)
+			{
+				if (!is_ignored (word[2]))
+					show_notificationf (word[1], _("Invited to channel by: %s (%s)"), word[2], network);
+			}
+			else
+			{
+				if (!is_ignored (word[1]))
+					show_notificationf (word[2], _("Notice from: %s (%s)"), word[1], network);
+			}
+		}
+		else
+			show_notificationf (word[2], _("Private message from: %s (%s)"), word[1], network);
+	}
+	return HEXCHAT_EAT_NONE;
+}
+
+static int
+tray_cmd_cb (char *word[], char *word_eol[], gpointer userdata)
+{
+	if (word[2] && !g_ascii_strcasecmp (word[2], "-b") && word[3] && word[4])
+	{
+		if (should_alert ())
+			show_notification (word[3], word_eol[4]);
+		return HEXCHAT_EAT_ALL;
+	}
+
+	return HEXCHAT_EAT_NONE;
+}
+
+int
+notification_plugin_init (hexchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg)
+{
+	if (!notification_backend_init ())
+		return 0;
+
+	ph = plugin_handle;
+	*plugin_name = "";
+	*plugin_desc = "";
+	*plugin_version = "";
+
+	hexchat_hook_print (ph, "Channel Msg Hilight", HEXCHAT_PRI_LOWEST, incoming_hilight_cb, NULL);
+	hexchat_hook_print (ph, "Channel Action Hilight", HEXCHAT_PRI_LOWEST, incoming_hilight_cb, NULL);
+
+	hexchat_hook_print (ph, "Channel Message", HEXCHAT_PRI_LOWEST, incoming_message_cb, NULL);
+	hexchat_hook_print (ph, "Channel Action", HEXCHAT_PRI_LOWEST, incoming_message_cb, NULL);
+	hexchat_hook_print (ph, "Channel Notice", HEXCHAT_PRI_LOWEST, incoming_message_cb, NULL);
+
+	hexchat_hook_print (ph, "Private Message", HEXCHAT_PRI_LOWEST, incoming_priv_cb, NULL);
+	hexchat_hook_print (ph, "Private Message to Dialog", HEXCHAT_PRI_LOWEST, incoming_priv_cb, NULL);
+	hexchat_hook_print (ph, "Private Action", HEXCHAT_PRI_LOWEST, incoming_priv_cb, NULL);
+	hexchat_hook_print (ph, "Private Action to Dialog", HEXCHAT_PRI_LOWEST, incoming_priv_cb, NULL);
+
+	/* Special events treated as priv */
+	hexchat_hook_print (ph, "Notice", HEXCHAT_PRI_LOWEST, incoming_priv_cb, GINT_TO_POINTER (1));
+	hexchat_hook_print (ph, "Invited", HEXCHAT_PRI_LOWEST, incoming_priv_cb, GINT_TO_POINTER (2));
+	hexchat_hook_print (ph, "DCC Offer", HEXCHAT_PRI_LOWEST, incoming_priv_cb, GINT_TO_POINTER (3));
+
+	hexchat_hook_command (ph, "TRAY", HEXCHAT_PRI_HIGH, tray_cmd_cb, NULL, NULL);
+	
+	return 1;
+}
+
+
+int
+notification_plugin_deinit (void)
+{
+	notification_backend_deinit ();
+	return 1;
+}
diff --git a/src/fe-gtk/plugin-notification.h b/src/fe-gtk/plugin-notification.h
new file mode 100644
index 00000000..07ad1609
--- /dev/null
+++ b/src/fe-gtk/plugin-notification.h
@@ -0,0 +1,25 @@
+/* HexChat
+ * Copyright (C) 2015 Patrick Griffis.
+ *
+ * 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 HEXCHAT_PLUGIN_NOTIFICATION_H
+#define HEXCHAT_PLUGIN_NOTIFICATION_H
+
+int notification_plugin_init (void *, char **, char **, char **, char *);
+int notification_plugin_deinit (void *);
+
+#endif
diff --git a/src/fe-gtk/plugin-tray.c b/src/fe-gtk/plugin-tray.c
index 3cd6502d..1ec8d2a3 100644
--- a/src/fe-gtk/plugin-tray.c
+++ b/src/fe-gtk/plugin-tray.c
@@ -34,18 +34,6 @@
 #include <unistd.h>
 #endif
 
-#ifdef USE_LIBNOTIFY
-#include <libnotify/notify.h>
-#ifndef NOTIFY_CHECK_VERSION
-#define NOTIFY_CHECK_VERSION(x,y,z) 0
-#endif
-#if NOTIFY_CHECK_VERSION(0,7,0)
-#define XC_NOTIFY_NEW(a,b,c,d) notify_notification_new(a,b,c)
-#else
-#define XC_NOTIFY_NEW(a,b,c,d) notify_notification_new(a,b,c,d)
-#endif
-#endif
-
 typedef enum	/* current icon status */
 {
 	TS_NONE,
@@ -154,83 +142,6 @@ fe_tray_set_tooltip (const char *text)
 		gtk_status_icon_set_tooltip_text (sticon, text);
 }
 
-void
-fe_tray_set_balloon (const char *title, const char *text)
-{
-#ifndef WIN32
-#if 0
-	const char *argv[8];
-	const char *path;
-	char time[16];
-#endif
-	WinStatus ws;
-
-	/* no balloons if the window is focused */
-	ws = tray_get_window_status ();
-	if ((prefs.hex_away_omit_alerts && hexchat_get_info(ph, "away")) ||
-		(prefs.hex_gui_focus_omitalerts && ws == WS_FOCUSED))
-		return;
-
-	/* bit 1 of flags means "no balloons unless hidden/iconified" */
-	if (ws != WS_HIDDEN && prefs.hex_gui_tray_quiet)
-		return;
-
-	/* FIXME: this should close the current balloon */
-	if (!text)
-		return;
-
-#ifdef USE_LIBNOTIFY
-	static int notify_text_strip_flags = STRIP_ALL;
-	NotifyNotification *notification;
-	char *notify_text, *notify_title;
-
-	if (!notify_is_initted())
-	{
-		GList* server_caps;
-		notify_init(PACKAGE_NAME);
-
-		server_caps = notify_get_server_caps ();
-		if (g_list_find_custom (server_caps, "body-markup", (GCompareFunc)strcmp))
-		{
-			notify_text_strip_flags |= STRIP_ESCMARKUP;
-		}
-		g_list_free_full (server_caps, g_free);
-	}
-
-	notify_text = strip_color (text, -1, notify_text_strip_flags);
-	notify_title = strip_color (title, -1, STRIP_ALL);
-
-	notification = XC_NOTIFY_NEW (notify_title, notify_text, HEXCHATSHAREDIR "/icons/hicolor/scalable/apps/hexchat.svg", NULL);
-
-#if NOTIFY_CHECK_VERSION(0,7,0)
-	notify_notification_set_hint (notification, "desktop-entry", g_variant_new_string ("hexchat"));
-#endif
-
-	g_free ((char *)notify_title);
-	g_free ((char *)notify_text);
-
-	notify_notification_set_timeout (notification, prefs.hex_input_balloon_time*1000);
-	notify_notification_show (notification, NULL);
-
-	g_object_unref (notification);
-#endif
-#endif
-}
-
-static void
-tray_set_balloonf (const char *text, const char *format, ...)
-{
-	va_list args;
-	char *buf;
-
-	va_start (args, format);
-	buf = g_strdup_vprintf (format, args);
-	va_end (args);
-
-	fe_tray_set_balloon (buf, text);
-	g_free (buf);
-}
-
 static void
 tray_set_tipf (const char *format, ...)
 {
@@ -719,10 +630,6 @@ tray_hilight_cb (char *word[], void *userdata)
 								tray_hilight_count, word[1], hexchat_get_info (ph, "channel"));
 	}
 
-	if (prefs.hex_input_balloon_hilight)
-		tray_set_balloonf (word[2], _("Highlighted message from: %s (%s)"),
-								 word[1], hexchat_get_info (ph, "channel"));
-
 	return HEXCHAT_EAT_NONE;
 }
 
@@ -744,10 +651,6 @@ tray_message_cb (char *word[], void *userdata)
 			tray_set_tipf (_(DISPLAY_NAME": %u channel messages."), tray_pub_count);
 	}
 
-	if (prefs.hex_input_balloon_chans)
-		tray_set_balloonf (word[2], _("Channel message from: %s (%s)"),
-								 word[1], hexchat_get_info (ph, "channel"));
-
 	return HEXCHAT_EAT_NONE;
 }
 
@@ -775,10 +678,6 @@ tray_priv (char *from, char *text)
 			tray_set_tipf (_(DISPLAY_NAME": %u private messages, latest from: %s (%s)"),
 								tray_priv_count, from, network);
 	}
-
-	if (prefs.hex_input_balloon_priv)
-		tray_set_balloonf (text, _("Private message from: %s (%s)"),
-								 from, network);
 }
 
 static int
@@ -823,10 +722,6 @@ tray_dcc_cb (char *word[], void *userdata)
 								tray_file_count, word[1], network);
 	}
 
-	if (prefs.hex_input_balloon_priv && (!prefs.hex_away_omit_alerts || tray_find_away_status () != 1))
-		tray_set_balloonf ("", _("File offer from: %s (%s)"),
-								word[1], network);
-
 	return HEXCHAT_EAT_NONE;
 }
 
@@ -905,8 +800,6 @@ tray_plugin_deinit (hexchat_plugin *plugin_handle)
 {
 #ifdef WIN32
 	tray_cleanup ();
-#elif defined(USE_LIBNOTIFY)
-	notify_uninit ();
 #endif
 	return 1;
 }
diff --git a/src/fe-gtk/setup.c b/src/fe-gtk/setup.c
index 6d06a0fa..11261560 100644
--- a/src/fe-gtk/setup.c
+++ b/src/fe-gtk/setup.c
@@ -36,6 +36,7 @@
 #include "pixmaps.h"
 #include "menu.h"
 #include "plugin-tray.h"
+#include "notifications/notification-backend.h"
 
 #ifdef WIN32
 #include "../common/fe.h"
@@ -397,9 +398,47 @@ static const setting alert_settings[] =
 	{ST_HEADER,	N_("Alerts"),0,0,0},
 
 	{ST_ALERTHEAD},
-#if !defined (WIN32) && !defined (__APPLE__)
-	{ST_3OGGLE, N_("Show tray balloons on:"), 0, 0, (void *)balloonlist, 0},
+
+
+	{ST_3OGGLE, N_("Show notifications on:"), 0, 0, (void *)balloonlist, 0},
+	{ST_3OGGLE, N_("Blink tray icon on:"), 0, 0, (void *)trayblinklist, 0},
+	{ST_3OGGLE, N_("Blink task bar on:"), 0, 0, (void *)taskbarlist, 0},
+#ifdef WIN32
+	{ST_3OGGLE, N_("Make a beep sound on:"), 0, N_("Play the \"Instant Message Notification\" system sound upon the selected events"), (void *)beeplist, 0},
+#else
+#ifdef USE_LIBCANBERRA
+	{ST_3OGGLE, N_("Make a beep sound on:"), 0, N_("Play \"message-new-instant\" from the freedesktop.org sound theme upon the selected events"), (void *)beeplist, 0},
+#else
+	{ST_3OGGLE, N_("Make a beep sound on:"), 0, N_("Play a GTK beep upon the selected events"), (void *)beeplist, 0},
+#endif
 #endif
+
+	{ST_TOGGLE,	N_("Omit alerts when marked as being away"), P_OFFINTNL(hex_away_omit_alerts), 0, 0, 0},
+	{ST_TOGGLE,	N_("Omit alerts while the window is focused"), P_OFFINTNL(hex_gui_focus_omitalerts), 0, 0, 0},
+
+	{ST_HEADER,	N_("Tray Behavior"), 0, 0, 0},
+	{ST_TOGGLE,	N_("Enable system tray icon"), P_OFFINTNL(hex_gui_tray), 0, 0, 4},
+	{ST_TOGGLE,	N_("Minimize to tray"), P_OFFINTNL(hex_gui_tray_minimize), 0, 0, 0},
+	{ST_TOGGLE,	N_("Close to tray"), P_OFFINTNL(hex_gui_tray_close), 0, 0, 0},
+	{ST_TOGGLE,	N_("Automatically mark away/back"), P_OFFINTNL(hex_gui_tray_away), N_("Automatically change status when hiding to tray."), 0, 0},
+	{ST_TOGGLE,	N_("Only show notifications when hidden or iconified"), P_OFFINTNL(hex_gui_tray_quiet), 0, 0, 0},
+
+	{ST_HEADER,	N_("Highlighted Messages"),0,0,0},
+	{ST_LABEL,	N_("Highlighted messages are ones where your nickname is mentioned, but also:"), 0, 0, 0, 1},
+
+	{ST_ENTRY,	N_("Extra words to highlight:"), P_OFFSETNL(hex_irc_extra_hilight), 0, 0, sizeof prefs.hex_irc_extra_hilight},
+	{ST_ENTRY,	N_("Nick names not to highlight:"), P_OFFSETNL(hex_irc_no_hilight), 0, 0, sizeof prefs.hex_irc_no_hilight},
+	{ST_ENTRY,	N_("Nick names to always highlight:"), P_OFFSETNL(hex_irc_nick_hilight), 0, 0, sizeof prefs.hex_irc_nick_hilight},
+	{ST_LABEL,	N_("Separate multiple words with commas.\nWildcards are accepted.")},
+
+	{ST_END, 0, 0, 0, 0, 0}
+};
+
+static const setting alert_settings_nonotifications[] =
+{
+	{ST_HEADER,	N_("Alerts"),0,0,0},
+
+	{ST_ALERTHEAD},
 	{ST_3OGGLE, N_("Blink tray icon on:"), 0, 0, (void *)trayblinklist, 0},
 #ifdef HAVE_GTK_MAC
 	{ST_3OGGLE, N_("Bounce dock icon on:"), 0, 0, (void *)taskbarlist, 0},
@@ -422,17 +461,10 @@ static const setting alert_settings[] =
 	{ST_TOGGLE,	N_("Omit alerts while the window is focused"), P_OFFINTNL(hex_gui_focus_omitalerts), 0, 0, 0},
 
 	{ST_HEADER,	N_("Tray Behavior"), 0, 0, 0},
-#ifdef WIN32
-	{ST_TOGGLE,	N_("Enable system tray icon"), P_OFFINTNL(hex_gui_tray), 0, 0, 3},
-#else
 	{ST_TOGGLE,	N_("Enable system tray icon"), P_OFFINTNL(hex_gui_tray), 0, 0, 4},
-#endif
 	{ST_TOGGLE,	N_("Minimize to tray"), P_OFFINTNL(hex_gui_tray_minimize), 0, 0, 0},
 	{ST_TOGGLE,	N_("Close to tray"), P_OFFINTNL(hex_gui_tray_close), 0, 0, 0},
 	{ST_TOGGLE,	N_("Automatically mark away/back"), P_OFFINTNL(hex_gui_tray_away), N_("Automatically change status when hiding to tray."), 0, 0},
-#ifndef WIN32
-	{ST_TOGGLE,	N_("Only show tray balloons when hidden or iconified"), P_OFFINTNL(hex_gui_tray_quiet), 0, 0, 0},
-#endif
 
 	{ST_HEADER,	N_("Highlighted Messages"),0,0,0},
 	{ST_LABEL,	N_("Highlighted messages are ones where your nickname is mentioned, but also:"), 0, 0, 0, 1},
@@ -450,7 +482,7 @@ static const setting alert_settings_unity[] =
 	{ST_HEADER,	N_("Alerts"),0,0,0},
 
 	{ST_ALERTHEAD},
-	{ST_3OGGLE, N_("Show tray balloons on:"), 0, 0, (void *)balloonlist, 0},
+	{ST_3OGGLE, N_("Show notifications on:"), 0, 0, (void *)balloonlist, 0},
 	{ST_3OGGLE, N_("Blink task bar on:"), 0, 0, (void *)taskbarlist, 0},
 	{ST_3OGGLE, N_("Make a beep sound on:"), 0, 0, (void *)beeplist, 0},
 
@@ -468,6 +500,28 @@ static const setting alert_settings_unity[] =
 	{ST_END, 0, 0, 0, 0, 0}
 };
 
+static const setting alert_settings_unityandnonotifications[] =
+{
+	{ST_HEADER, N_("Alerts"), 0, 0, 0},
+
+	{ST_ALERTHEAD},
+	{ST_3OGGLE, N_("Blink task bar on:"), 0, 0, (void *)taskbarlist, 0},
+	{ST_3OGGLE, N_("Make a beep sound on:"), 0, 0, (void *)beeplist, 0},
+
+	{ST_TOGGLE, N_("Omit alerts when marked as being away"), P_OFFINTNL (hex_away_omit_alerts), 0, 0, 0},
+	{ST_TOGGLE, N_("Omit alerts while the window is focused"), P_OFFINTNL (hex_gui_focus_omitalerts), 0, 0, 0},
+
+	{ST_HEADER, N_("Highlighted Messages"), 0, 0, 0},
+	{ST_LABEL, N_("Highlighted messages are ones where your nickname is mentioned, but also:"), 0, 0, 0, 1},
+
+	{ST_ENTRY, N_("Extra words to highlight:"), P_OFFSETNL (hex_irc_extra_hilight), 0, 0, sizeof prefs.hex_irc_extra_hilight},
+	{ST_ENTRY, N_("Nick names not to highlight:"), P_OFFSETNL (hex_irc_no_hilight), 0, 0, sizeof prefs.hex_irc_no_hilight},
+	{ST_ENTRY, N_("Nick names to always highlight:"), P_OFFSETNL (hex_irc_nick_hilight), 0, 0, sizeof prefs.hex_irc_nick_hilight},
+	{ST_LABEL, N_("Separate multiple words with commas.\nWildcards are accepted.")},
+
+	{ST_END, 0, 0, 0, 0, 0}
+};
+
 static const setting general_settings[] =
 {
 	{ST_HEADER,	N_("Default Messages"),0,0,0},
@@ -1832,10 +1886,18 @@ setup_create_pages (GtkWidget *box)
 
 	setup_add_page (cata[8], book, setup_create_page (general_settings));
 
-	if (unity_mode ())
+	if (unity_mode () && !notification_backend_supported ())
+	{
+		setup_add_page (cata[9], book, setup_create_page (alert_settings_unityandnonotifications));
+	}
+	else if (unity_mode ())
 	{
 		setup_add_page (cata[9], book, setup_create_page (alert_settings_unity));
 	}
+	else if (!notification_backend_supported ())
+	{
+		setup_add_page (cata[9], book, setup_create_page (alert_settings_nonotifications));
+	}
 	else
 	{
 		setup_add_page (cata[9], book, setup_create_page (alert_settings));
diff --git a/src/fe-text/fe-text.c b/src/fe-text/fe-text.c
index a709fe9e..7b4576da 100644
--- a/src/fe-text/fe-text.c
+++ b/src/fe-text/fe-text.c
@@ -902,7 +902,6 @@ void fe_tray_set_flash (const char *filename1, const char *filename2, int timeou
 void fe_tray_set_file (const char *filename){}
 void fe_tray_set_icon (feicon icon){}
 void fe_tray_set_tooltip (const char *text){}
-void fe_tray_set_balloon (const char *title, const char *text){}
 void fe_userlist_update (session *sess, struct User *user){}
 void
 fe_open_chan_list (server *serv, char *filter, int do_refresh)
diff --git a/src/fe-gtk/hexchat.exe.manifest b/win32/hexchat.exe.manifest
index 39c4eb4c..1ea11920 100644
--- a/src/fe-gtk/hexchat.exe.manifest
+++ b/win32/hexchat.exe.manifest
@@ -19,4 +19,14 @@
       />
     </dependentAssembly>
   </dependency>
-</assembly>
+  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+    <application>
+      <!--This Id value indicates the application supports Windows 7 functionality-->
+      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+      <!--This Id value indicates the application supports Windows 8 functionality-->
+      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+      <!--This Id value indicates the application supports Windows 8.1 functionality-->
+      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+    </application>
+  </compatibility>
+</assembly>
\ No newline at end of file
diff --git a/win32/hexchat.props b/win32/hexchat.props
index 1d0f5845..32588334 100644
--- a/win32/hexchat.props
+++ b/win32/hexchat.props
@@ -90,6 +90,7 @@ copy "$(HexChatBin)hcmpcinfo.dll" "$(HexChatRel)\plugins"
 copy "$(HexChatBin)hcperl.dll" "$(HexChatRel)\plugins"

 copy "$(HexChatBin)hcpython2.dll" "$(HexChatRel)\plugins"

 copy "$(HexChatBin)hcpython3.dll" "$(HexChatRel)\plugins"

+copy "$(HexChatBin)hcnotifications-winrt.dll" "$(HexChatRel)\plugins"

 copy "$(HexChatBin)hcupd.dll" "$(HexChatRel)\plugins"

 copy "$(HexChatBin)hcwinamp.dll" "$(HexChatRel)\plugins"

 copy "$(HexChatBin)hcsysinfo.dll" "$(HexChatRel)\plugins"

diff --git a/win32/hexchat.sln b/win32/hexchat.sln
index 03b75c5d..0321261d 100644
--- a/win32/hexchat.sln
+++ b/win32/hexchat.sln
@@ -92,6 +92,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "copy", "copy\copy.vcxproj",
 		{E78C0D9A-798E-4BF6-B0CC-6FECB8CA2FCE} = {E78C0D9A-798E-4BF6-B0CC-6FECB8CA2FCE}

 		{E4BDB4C8-2335-415A-ACEE-BA88B19BFE82} = {E4BDB4C8-2335-415A-ACEE-BA88B19BFE82}

 		{DE87FFCA-9606-4116-B747-062D88A56A28} = {DE87FFCA-9606-4116-B747-062D88A56A28}

+		{C53145CC-D021-40C9-B97C-0249AB9A43C9} = {C53145CC-D021-40C9-B97C-0249AB9A43C9}

 		{D90BC3E3-1341-4849-9354-5F40489D39D1} = {D90BC3E3-1341-4849-9354-5F40489D39D1}

 		{3C4F42FC-292A-420B-B63D-C03DFBDD8E4E} = {3C4F42FC-292A-420B-B63D-C03DFBDD8E4E}

 	EndProjectSection

@@ -119,6 +120,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "python3", "..\plugins\pytho
 		{87554B59-006C-4D94-9714-897B27067BA3} = {87554B59-006C-4D94-9714-897B27067BA3}

 	EndProjectSection

 EndProject

+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "notifications-winrt", "..\src\fe-gtk\notifications\notifications-winrt.vcxproj", "{C53145CC-D021-40C9-B97C-0249AB9A43C9}"

+EndProject

 Global

 	GlobalSection(SolutionConfigurationPlatforms) = preSolution

 		Release|Win32 = Release|Win32

@@ -201,16 +204,19 @@ Global
 		{C2321A03-0BA7-45B3-8740-ABD82B36B0BF}.Release|Win32.Build.0 = Release|Win32

 		{C2321A03-0BA7-45B3-8740-ABD82B36B0BF}.Release|x64.ActiveCfg = Release|x64

 		{C2321A03-0BA7-45B3-8740-ABD82B36B0BF}.Release|x64.Build.0 = Release|x64

+		{C53145CC-D021-40C9-B97C-0249AB9A43C9}.Release|Win32.ActiveCfg = Release|Win32

+		{C53145CC-D021-40C9-B97C-0249AB9A43C9}.Release|Win32.Build.0 = Release|Win32

+		{C53145CC-D021-40C9-B97C-0249AB9A43C9}.Release|x64.ActiveCfg = Release|x64

+		{C53145CC-D021-40C9-B97C-0249AB9A43C9}.Release|x64.Build.0 = Release|x64

 	EndGlobalSection

 	GlobalSection(SolutionProperties) = preSolution

 		HideSolutionNode = FALSE

 	EndGlobalSection

 	GlobalSection(NestedProjects) = preSolution

+		{87554B59-006C-4D94-9714-897B27067BA3} = {AAACEB12-9475-410E-AF5A-FDFF907E9043}

 		{E4BDB4C8-2335-415A-ACEE-BA88B19BFE82} = {AAACEB12-9475-410E-AF5A-FDFF907E9043}

 		{E93E1255-95D1-4B08-8FDF-B53CC6A21280} = {AAACEB12-9475-410E-AF5A-FDFF907E9043}

-		{87554B59-006C-4D94-9714-897B27067BA3} = {AAACEB12-9475-410E-AF5A-FDFF907E9043}

-		{DE87FFCA-9606-4116-B747-062D88A56A28} = {AAACEB12-9475-410E-AF5A-FDFF907E9043}

-		{A7D7CE59-2A31-48AE-BED2-A9828E241832} = {AAACEB12-9475-410E-AF5A-FDFF907E9043}

+		{19C52A0A-A790-409E-A28A-9745FF990F5C} = {D237DA6B-BD5F-46C0-8BEA-50E9A1340240}

 		{4980AF24-9D42-427D-A8E6-0DF3B97C455D} = {561126F4-FA18-45FC-A2BF-8F858F161D6D}

 		{5EF7F47D-D09C-43C4-BF64-B28B11A0FF91} = {561126F4-FA18-45FC-A2BF-8F858F161D6D}

 		{17E4BE39-76F7-4A06-AD21-EFD0C5091F76} = {561126F4-FA18-45FC-A2BF-8F858F161D6D}

@@ -219,11 +225,13 @@ Global
 		{461DC24A-A410-4171-8C02-CCDBF3702C2A} = {561126F4-FA18-45FC-A2BF-8F858F161D6D}

 		{E78C0D9A-798E-4BF6-B0CC-6FECB8CA2FCE} = {561126F4-FA18-45FC-A2BF-8F858F161D6D}

 		{6C0CA980-97C5-427A-BE61-5BCECAFABBDA} = {561126F4-FA18-45FC-A2BF-8F858F161D6D}

-		{19C52A0A-A790-409E-A28A-9745FF990F5C} = {D237DA6B-BD5F-46C0-8BEA-50E9A1340240}

-		{D90BC3E3-1341-4849-9354-5F40489D39D1} = {D237DA6B-BD5F-46C0-8BEA-50E9A1340240}

-		{C2321A03-0BA7-45B3-8740-ABD82B36B0BF} = {D237DA6B-BD5F-46C0-8BEA-50E9A1340240}

 		{B10A2C41-344C-43E0-A32D-B9587C198D8B} = {0FD996A7-464F-4981-8380-3DCA3A244A13}

 		{C9B735E4-75BC-45AC-A5E3-39A6D076F912} = {0FD996A7-464F-4981-8380-3DCA3A244A13}

 		{5A0F4962-E670-4DA2-9E45-52CC47F26E2F} = {0FD996A7-464F-4981-8380-3DCA3A244A13}

+		{DE87FFCA-9606-4116-B747-062D88A56A28} = {AAACEB12-9475-410E-AF5A-FDFF907E9043}

+		{A7D7CE59-2A31-48AE-BED2-A9828E241832} = {AAACEB12-9475-410E-AF5A-FDFF907E9043}

+		{D90BC3E3-1341-4849-9354-5F40489D39D1} = {D237DA6B-BD5F-46C0-8BEA-50E9A1340240}

+		{C2321A03-0BA7-45B3-8740-ABD82B36B0BF} = {D237DA6B-BD5F-46C0-8BEA-50E9A1340240}

+		{C53145CC-D021-40C9-B97C-0249AB9A43C9} = {561126F4-FA18-45FC-A2BF-8F858F161D6D}

 	EndGlobalSection

 EndGlobal

diff --git a/win32/installer/hexchat.iss.tt b/win32/installer/hexchat.iss.tt
index e2d0943d..216a92c0 100644
--- a/win32/installer/hexchat.iss.tt
+++ b/win32/installer/hexchat.iss.tt
@@ -148,6 +148,8 @@ Source: "pixman-1.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
 Source: "ssleay32.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
 Source: "zlib1.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs
 
+Source: "plugins\hcnotifications-winrt.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: libs
+
 Source: "lib\enchant\libenchant_myspell.dll"; DestDir: "{app}\lib\enchant"; Flags: ignoreversion; Components: libs
 
 Source: "lib\gtk-2.0\i686-pc-vs10\engines\*"; DestDir: "{app}\lib\gtk-2.0\i686-pc-vs10\engines"; Flags: ignoreversion; Components: libs
@@ -173,7 +175,7 @@ Source: "hexchat-text.exe"; DestDir: "{app}"; Flags: ignoreversion; Components:
 Source: "thememan.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: xtm
 
 [Icons]
-Name: "{group}\HexChat"; Filename: "{app}\hexchat.exe"; Tasks: not portable
+Name: "{group}\HexChat"; Filename: "{app}\hexchat.exe"; AppUserModelID: "HexChat.Desktop.Notify"; Tasks: not portable
 Name: "{group}\HexChat Safe Mode"; Filename: "{app}\hexchat.exe"; Parameters: "--no-auto --no-plugins"; Tasks: not portable
 Name: "{group}\HexChat ChangeLog"; Filename: "{app}\changelog.url"; IconFilename: "{sys}\shell32.dll"; IconIndex: 165; Tasks: not portable
 Name: "{group}\HexChat ReadMe"; Filename: "{app}\readme.url"; IconFilename: "{sys}\shell32.dll"; IconIndex: 23; Tasks: not portable