summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Markmann <tm@ayena.de>2015-09-03 16:01:14 (GMT)
committerTobias Markmann <tm@ayena.de>2015-09-03 16:20:31 (GMT)
commitbe6aa6e81b44be67518731d67bb2b72268d351e8 (patch)
treeeaa06c5bf303e627db91f869adba0611da393255
parentb6ffd5a332b6b21fdba9937fa3a0274556a09cdf (diff)
downloadswift-be6aa6e81b44be67518731d67bb2b72268d351e8.zip
swift-be6aa6e81b44be67518731d67bb2b72268d351e8.tar.bz2
Initial support for OS X Notification Center
This implements basic support for OS X Notification Center notifications with simple banner notifications showing type, contact and message/presence information. A click on the notification opens the chat view to the contact. The Notification Center backend will be used on OS X if the Growl notification backend is not used. This code requires OS X version 10.8 or later. Test-Information: Tested presence and message notifications between multiple Swift accounts and instances on OS X 10.9.5. Change-Id: I7b9e2132cab25e086e0912191562cad8f4cbae38
-rw-r--r--SwifTools/Notifier/NotificationCenterNotifier.h38
-rw-r--r--SwifTools/Notifier/NotificationCenterNotifier.mm87
-rw-r--r--SwifTools/Notifier/NotificationCenterNotifierDelegate.h22
-rw-r--r--SwifTools/Notifier/NotificationCenterNotifierDelegate.mm26
-rw-r--r--SwifTools/Notifier/SConscript6
-rw-r--r--Swift/QtUI/QtSwift.cpp4
6 files changed, 183 insertions, 0 deletions
diff --git a/SwifTools/Notifier/NotificationCenterNotifier.h b/SwifTools/Notifier/NotificationCenterNotifier.h
new file mode 100644
index 0000000..0d43c5b
--- /dev/null
+++ b/SwifTools/Notifier/NotificationCenterNotifier.h
@@ -0,0 +1,38 @@
1/*
2 * Copyright (c) 2015 Isode Limited.
3 * All rights reserved.
4 * See the COPYING file for more information.
5 */
6
7#pragma once
8
9#include <string>
10
11#include <SwifTools/Notifier/Notifier.h>
12
13namespace Swift {
14
15/**
16 * @brief The NotificationCenterNotifier class implmenents the notification interface for the
17 * OS X Notification Center API.
18 */
19class NotificationCenterNotifier : public Notifier {
20public:
21 NotificationCenterNotifier();
22 virtual ~NotificationCenterNotifier();
23
24 virtual void showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void ()> callback);
25 virtual void purgeCallbacks();
26
27 /**
28 * @brief The handleUserNotificationActivated is called by the delegate, when a user activates/clicks on a notification.
29 * @param identifier The std::string UUID identifiying the notification.
30 */
31 void handleUserNotificationActivated(const std::string& identifier);
32
33private:
34 class Private;
35 boost::shared_ptr<Private> p;
36};
37
38}
diff --git a/SwifTools/Notifier/NotificationCenterNotifier.mm b/SwifTools/Notifier/NotificationCenterNotifier.mm
new file mode 100644
index 0000000..df092ff
--- /dev/null
+++ b/SwifTools/Notifier/NotificationCenterNotifier.mm
@@ -0,0 +1,87 @@
1/*
2 * Copyright (c) 2015 Isode Limited.
3 * All rights reserved.
4 * See the COPYING file for more information.
5 */
6
7#include <SwifTools/Notifier/NotificationCenterNotifier.h>
8
9#include <map>
10#include <string>
11
12#include <boost/smart_ptr/make_shared.hpp>
13
14#include <Swiften/Base/Log.h>
15
16#import <Cocoa/Cocoa.h>
17
18#include <SwifTools/Notifier/NotificationCenterNotifierDelegate.h>
19#include <SwifTools/Cocoa/CocoaUtil.h>
20
21namespace {
22 struct Context {
23 Context(const boost::function<void()>& callback) : callback(new boost::function<void()>(callback)) {
24 }
25
26 ~Context() {
27 delete callback;
28 }
29
30 boost::function<void()>* callback;
31 };
32}
33
34namespace Swift {
35
36class NotificationCenterNotifier::Private {
37 public:
38 std::map<std::string, boost::shared_ptr<Context> > callbacksForNotifications;
39 boost::intrusive_ptr<NotificationCenterNotifierDelegate> delegate;
40};
41
42NotificationCenterNotifier::NotificationCenterNotifier() {
43 p = boost::make_shared<Private>();
44 p->delegate = boost::intrusive_ptr<NotificationCenterNotifierDelegate>([[NotificationCenterNotifierDelegate alloc] init], false);
45 [p->delegate.get() setNotifier: this];
46
47 [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate: p->delegate.get()];
48}
49
50NotificationCenterNotifier::~NotificationCenterNotifier() {
51 [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate: nil];
52 p->callbacksForNotifications.clear();
53}
54
55void NotificationCenterNotifier::showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function<void ()> callback) {
56 NSUserNotification* notification = [[NSUserNotification alloc] init];
57 notification.title = STD2NSSTRING(typeToString(type));
58 notification.subtitle = STD2NSSTRING(subject);
59 notification.informativeText = STD2NSSTRING(description);
60 notification.contentImage = [[NSImage alloc] initWithContentsOfFile: STD2NSSTRING(picture.string())];
61
62 // The OS X Notification Center API does not allow to attach custom data, like a pointer to a callback function,
63 // to the NSUserNotification object. Therefore we maintain a mapping from a NSUserNotification instance's identification
64 // to their respective callbacks.
65 notification.identifier = [[NSUUID UUID] UUIDString];
66
67 /// \todo Currently the elements are only removed on application exit. Ideally the notifications not required anymore
68 /// are removed from the map; e.g. when visiting a chat view, all notifications from that view can be removed from
69 /// the map and the NSUserNotificationCenter.
70 p->callbacksForNotifications[NS2STDSTRING(notification.identifier)] = boost::make_shared<Context>(callback);
71 [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
72}
73
74void NotificationCenterNotifier::purgeCallbacks() {
75 p->callbacksForNotifications.clear();
76}
77
78void NotificationCenterNotifier::handleUserNotificationActivated(const std::string& identifier) {
79 if (p->callbacksForNotifications.find(identifier) != p->callbacksForNotifications.end()) {
80 (*p->callbacksForNotifications[identifier]->callback)();
81 }
82 else {
83 SWIFT_LOG(warning) << "Missing callback entry for activated notification. The activate notification may come from another instance." << std::endl;
84 }
85}
86
87}
diff --git a/SwifTools/Notifier/NotificationCenterNotifierDelegate.h b/SwifTools/Notifier/NotificationCenterNotifierDelegate.h
new file mode 100644
index 0000000..ea8fae0
--- /dev/null
+++ b/SwifTools/Notifier/NotificationCenterNotifierDelegate.h
@@ -0,0 +1,22 @@
1/*
2 * Copyright (c) 2015 Isode Limited.
3 * All rights reserved.
4 * See the COPYING file for more information.
5 */
6
7#pragma once
8
9#import <Cocoa/Cocoa.h>
10
11namespace Swift {
12 class NotificationCenterNotifier;
13}
14
15@interface NotificationCenterNotifierDelegate : NSObject<NSUserNotificationCenterDelegate> {
16}
17
18@property (nonatomic) Swift::NotificationCenterNotifier* notifier;
19
20- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification;
21
22@end
diff --git a/SwifTools/Notifier/NotificationCenterNotifierDelegate.mm b/SwifTools/Notifier/NotificationCenterNotifierDelegate.mm
new file mode 100644
index 0000000..617619c
--- /dev/null
+++ b/SwifTools/Notifier/NotificationCenterNotifierDelegate.mm
@@ -0,0 +1,26 @@
1/*
2 * Copyright (c) 2015 Isode Limited.
3 * All rights reserved.
4 * See the COPYING file for more information.
5 */
6
7#import "SwifTools/Notifier/NotificationCenterNotifierDelegate.h"
8
9#include <string>
10
11#include <SwifTools/Cocoa/CocoaUtil.h>
12#include <SwifTools/Notifier/NotificationCenterNotifier.h>
13
14@implementation NotificationCenterNotifierDelegate
15
16using namespace Swift;
17
18@synthesize notifier;
19
20- (void)userNotificationCenter:(NSUserNotificationCenter *) center didActivateNotification:(NSUserNotification *)notification {
21 (void)center;
22 std::string identifier = NS2STDSTRING(notification.identifier);
23 notifier->handleUserNotificationActivated(identifier);
24}
25
26@end
diff --git a/SwifTools/Notifier/SConscript b/SwifTools/Notifier/SConscript
index 98b5400..e60937b 100644
--- a/SwifTools/Notifier/SConscript
+++ b/SwifTools/Notifier/SConscript
@@ -9,10 +9,16 @@ sources = [
9if swiftools_env.get("HAVE_GROWL", False) : 9if swiftools_env.get("HAVE_GROWL", False) :
10 sources += [ 10 sources += [
11 "GrowlNotifier.mm", 11 "GrowlNotifier.mm",
12 "GrowlNotifierDelegate.mm", 12 "GrowlNotifierDelegate.mm",
13 ] 13 ]
14elif myenv["PLATFORM"] == "darwin" :
15 sources += [
16 "NotificationCenterNotifier.mm",
17 "NotificationCenterNotifierDelegate.mm",
18 ]
19
14if swiftools_env.get("HAVE_SNARL", False) : 20if swiftools_env.get("HAVE_SNARL", False) :
15 myenv.MergeFlags(myenv["SNARL_FLAGS"]) 21 myenv.MergeFlags(myenv["SNARL_FLAGS"])
16 sources += [ 22 sources += [
17 "SnarlNotifier.cpp", 23 "SnarlNotifier.cpp",
18 ] 24 ]
diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp
index 6d8ac7b..756f530 100644
--- a/Swift/QtUI/QtSwift.cpp
+++ b/Swift/QtUI/QtSwift.cpp
@@ -54,10 +54,12 @@
54#include <Swift/QtUI/WindowsNotifier.h> 54#include <Swift/QtUI/WindowsNotifier.h>
55#elif defined(HAVE_GROWL) 55#elif defined(HAVE_GROWL)
56#include <SwifTools/Notifier/GrowlNotifier.h> 56#include <SwifTools/Notifier/GrowlNotifier.h>
57#elif defined(SWIFTEN_PLATFORM_LINUX) 57#elif defined(SWIFTEN_PLATFORM_LINUX)
58#include <Swift/QtUI/FreeDesktopNotifier.h> 58#include <Swift/QtUI/FreeDesktopNotifier.h>
59#elif defined(SWIFTEN_PLATFORM_MACOSX)
60#include <SwifTools/Notifier/NotificationCenterNotifier.h>
59#else 61#else
60#include <SwifTools/Notifier/NullNotifier.h> 62#include <SwifTools/Notifier/NullNotifier.h>
61#endif 63#endif
62 64
63#if defined(SWIFTEN_PLATFORM_MACOSX) 65#if defined(SWIFTEN_PLATFORM_MACOSX)
@@ -194,10 +196,12 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa
194 notifier_ = new GrowlNotifier(SWIFT_APPLICATION_NAME); 196 notifier_ = new GrowlNotifier(SWIFT_APPLICATION_NAME);
195#elif defined(SWIFTEN_PLATFORM_WINDOWS) 197#elif defined(SWIFTEN_PLATFORM_WINDOWS)
196 notifier_ = new WindowsNotifier(SWIFT_APPLICATION_NAME, applicationPathProvider_->getResourcePath("/images/logo-icon-32.png"), systemTray->getQSystemTrayIcon()); 198 notifier_ = new WindowsNotifier(SWIFT_APPLICATION_NAME, applicationPathProvider_->getResourcePath("/images/logo-icon-32.png"), systemTray->getQSystemTrayIcon());
197#elif defined(SWIFTEN_PLATFORM_LINUX) 199#elif defined(SWIFTEN_PLATFORM_LINUX)
198 notifier_ = new FreeDesktopNotifier(SWIFT_APPLICATION_NAME); 200 notifier_ = new FreeDesktopNotifier(SWIFT_APPLICATION_NAME);
201#elif defined(SWIFTEN_PLATFORM_MACOSX)
202 notifier_ = new NotificationCenterNotifier();
199#else 203#else
200 notifier_ = new NullNotifier(); 204 notifier_ = new NullNotifier();
201#endif 205#endif
202 206
203#if defined(SWIFTEN_PLATFORM_MACOSX) 207#if defined(SWIFTEN_PLATFORM_MACOSX)