From 9d55b647520acc73742695517615f96165ecc8f5 Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Sat, 8 Sep 2012 16:15:31 +0200 Subject: Initial version of ML's NotificationCenter support. diff --git a/BuildTools/SCons/SConscript.boot b/BuildTools/SCons/SConscript.boot index b049f94..a741aab 100644 --- a/BuildTools/SCons/SConscript.boot +++ b/BuildTools/SCons/SConscript.boot @@ -36,6 +36,7 @@ if os.name == "nt" : if os.name == "nt" : vars.Add(PackageVariable("bonjour", "Bonjour SDK location", "yes")) vars.Add(PackageVariable("openssl", "OpenSSL location", "yes")) +vars.Add(PackageVariable("notification_center", "enable OS X Mountain Lion notification center", "no")) vars.Add(PathVariable("boost_includedir", "Boost headers location", None, PathVariable.PathAccept)) vars.Add(PathVariable("boost_libdir", "Boost library location", None, PathVariable.PathAccept)) vars.Add(PathVariable("expat_includedir", "Expat headers location", None, PathVariable.PathAccept)) diff --git a/BuildTools/SCons/SConstruct b/BuildTools/SCons/SConstruct index 3be4bd7..8a7e9ab 100644 --- a/BuildTools/SCons/SConstruct +++ b/BuildTools/SCons/SConstruct @@ -230,6 +230,11 @@ if env["PLATFORM"] == "darwin" : env["SPARKLE_FRAMEWORK"] = "/Library/Frameworks/Sparkle.framework" conf.Finish() +# Notification Center +env["HAVE_NOTIFICATION_CENTER"] = 0 +if env["PLATFORM"] == "darwin" : + env["HAVE_NOTIFICATION_CENTER"] = bool(env["notification_center"]) + # Growl env["HAVE_GROWL"] = 0 if env["PLATFORM"] == "darwin" : diff --git a/SwifTools/Notifier/NotificationCenterNotifier.h b/SwifTools/Notifier/NotificationCenterNotifier.h new file mode 100644 index 0000000..337f224 --- /dev/null +++ b/SwifTools/Notifier/NotificationCenterNotifier.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include + +#include + +namespace Swift { + class NotificationCenterNotifier : public Notifier { + public: + NotificationCenterNotifier(const std::string& name); + virtual ~NotificationCenterNotifier(); + + virtual void showMessage(Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& picture, boost::function callback); + + virtual void purgeCallbacks(); + + static bool isSupported(); + void handleNotificationClicked(void* notification); + + public: + class Private; + boost::shared_ptr p; + }; +} diff --git a/SwifTools/Notifier/NotificationCenterNotifier.mm b/SwifTools/Notifier/NotificationCenterNotifier.mm new file mode 100644 index 0000000..46bc7b1 --- /dev/null +++ b/SwifTools/Notifier/NotificationCenterNotifier.mm @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include + +#include + +#import +#import +#import +#import + +#include +#include + +#include + +#include + +namespace Swift { + +class NotificationCenterNotifier::Private { + public: + void handleNotificationClicked(NSUserNotification* notification) { + unsigned long int id = [[[notification userInfo] objectForKey:@"id"] unsignedLongValue]; + if (callbacks.find(id) != callbacks.end()) { + callbacks[id](); + callbacks.erase(id); + } else { + SWIFT_LOG(debug) << "Callback missing! id:"<< id << std::endl; + } + } + + public: + unsigned long int lastID; + NSUserNotificationCenter* notificationCenter; + boost::intrusive_ptr delegate; + std::map > callbacks; +}; + +NotificationCenterNotifier::NotificationCenterNotifier(const std::string& /*name*/) { + assert(isSupported()); + p = boost::make_shared(); + p->lastID = 0; + p->delegate = boost::intrusive_ptr([[NotificationCenterNotifierDelegate alloc] init], false); + p->delegate.get().notifier = this; + p->notificationCenter = [NSUserNotificationCenter defaultUserNotificationCenter]; + [p->notificationCenter setDelegate:p->delegate.get()]; +} + +NotificationCenterNotifier::~NotificationCenterNotifier() { + +} + +void NotificationCenterNotifier::showMessage(Notifier::Type type, const std::string& subject, const std::string& description, const boost::filesystem::path& /* picture */, boost::function callback) { + std::vector defaultTypes = getDefaultTypes(); + if (std::find(defaultTypes.begin(), defaultTypes.end(), type) == defaultTypes.end()) { + return; + } + + unsigned long int currentID = ++(p->lastID); + + NSUserNotification *notification = [[NSUserNotification alloc] init]; + [notification setTitle: [NSString stringWithUTF8String:subject.c_str()]]; + [notification setInformativeText: [NSString stringWithUTF8String:description.c_str()]]; + //[notification setActionButtonTitle:@"Accept Invitation"]; + //[notification setHasActionButton:TRUE]; + //[notification setSoundName:NSUserNotificationDefaultSoundName]; + [notification setUserInfo: [NSDictionary dictionaryWithObject: [NSNumber numberWithUnsignedLong:currentID] forKey:@"id"]]; + p->callbacks[currentID] = callback; + [p->notificationCenter scheduleNotification:notification]; +} + +void NotificationCenterNotifier::purgeCallbacks() { + p->callbacks.clear(); +} + +bool NotificationCenterNotifier::isSupported() { + return NSClassFromString(@"NSUserNotificationCenter") != nil; +} + +void NotificationCenterNotifier::handleNotificationClicked(void *notification) { + p->handleNotificationClicked(static_cast(notification)); +} + +} diff --git a/SwifTools/Notifier/NotificationCenterNotifierDelegate.h b/SwifTools/Notifier/NotificationCenterNotifierDelegate.h new file mode 100644 index 0000000..0db4370 --- /dev/null +++ b/SwifTools/Notifier/NotificationCenterNotifierDelegate.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#import + +namespace Swift { + class NotificationCenterNotifier; +} + +@interface NotificationCenterNotifierDelegate : NSObject { + Swift::NotificationCenterNotifier* notifier; +} + +@property (nonatomic) Swift::NotificationCenterNotifier* notifier; + +- (void) userNotificationCenter:(NSUserNotificationCenter *) center didActivateNotification:(NSUserNotification *) notification; + +@end diff --git a/SwifTools/Notifier/NotificationCenterNotifierDelegate.mm b/SwifTools/Notifier/NotificationCenterNotifierDelegate.mm new file mode 100644 index 0000000..271d953 --- /dev/null +++ b/SwifTools/Notifier/NotificationCenterNotifierDelegate.mm @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2012 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#import "NotificationCenterNotifierDelegate.h" + +#include + +@implementation NotificationCenterNotifierDelegate; + +@synthesize notifier; + +using namespace Swift; + +- (void) userNotificationCenter:(NSUserNotificationCenter *) center didActivateNotification:(NSUserNotification *) notification { + notifier->handleNotificationClicked(notification); + //Remove the notification + [center removeDeliveredNotification:notification]; +} + +@end diff --git a/SwifTools/Notifier/SConscript b/SwifTools/Notifier/SConscript index 98b5400..53bb38e 100644 --- a/SwifTools/Notifier/SConscript +++ b/SwifTools/Notifier/SConscript @@ -16,6 +16,11 @@ if swiftools_env.get("HAVE_SNARL", False) : sources += [ "SnarlNotifier.cpp", ] +if swiftools_env.get("HAVE_NOTIFICATION_CENTER", False) : + sources += [ + "NotificationCenterNotifier.mm", + "NotificationCenterNotifierDelegate.mm", + ] objects = myenv.StaticObject(sources) swiftools_env.Append(SWIFTOOLS_OBJECTS = objects) diff --git a/Swift/QtUI/QtSwift.cpp b/Swift/QtUI/QtSwift.cpp index 13b2175..c07c485 100644 --- a/Swift/QtUI/QtSwift.cpp +++ b/Swift/QtUI/QtSwift.cpp @@ -43,6 +43,9 @@ #include "WindowsNotifier.h" #elif defined(HAVE_GROWL) #include "SwifTools/Notifier/GrowlNotifier.h" +#if defined(HAVE_NOTIFICATION_CENTER) +#include "SwifTools/Notifier/NotificationCenterNotifier.h" +#endif #elif defined(SWIFTEN_PLATFORM_LINUX) #include "FreeDesktopNotifier.h" #else @@ -163,7 +166,13 @@ QtSwift::QtSwift(const po::variables_map& options) : networkFactories_(&clientMa QtSystemTray* systemTray = new QtSystemTray(); systemTrays_.push_back(systemTray); -#if defined(HAVE_GROWL) +#if defined(HAVE_NOTIFICATION_CENTER) && defined(HAVE_GROWL) + if (NotificationCenterNotifier::isSupported()) { + notifier_ = new NotificationCenterNotifier(SWIFT_APPLICATION_NAME); + } else { + notifier_ = new GrowlNotifier(SWIFT_APPLICATION_NAME); + } +#elif defined(HAVE_GROWL) notifier_ = new GrowlNotifier(SWIFT_APPLICATION_NAME); #elif defined(SWIFTEN_PLATFORM_WINDOWS) notifier_ = new WindowsNotifier(SWIFT_APPLICATION_NAME, applicationPathProvider_->getResourcePath("/images/logo-icon-32.png"), systemTray->getQSystemTrayIcon()); diff --git a/Swift/QtUI/QtWebView.cpp b/Swift/QtUI/QtWebView.cpp index 388f06a..38ed345 100644 --- a/Swift/QtUI/QtWebView.cpp +++ b/Swift/QtUI/QtWebView.cpp @@ -58,7 +58,7 @@ void QtWebView::contextMenuEvent(QContextMenuEvent* ev) { } } if (removeAction) { - menu->removeAction(action); + //menu->removeAction(action); } } diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index 5ab9c9e..4cd7865 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -40,6 +40,8 @@ if myenv["swift_mobile"] : if myenv.get("HAVE_SNARL", False) : myenv.UseFlags(myenv["SNARL_FLAGS"]) myenv.Append(CPPDEFINES = ["HAVE_SNARL"]) +if myenv.get("HAVE_NOTIFICATION_CENTER", False) : + myenv.Append(CPPDEFINES = ["HAVE_NOTIFICATION_CENTER"]) if env["PLATFORM"] == "win32" : myenv.Append(LIBS = ["cryptui"]) myenv.UseFlags(myenv["PLATFORM_FLAGS"]) -- cgit v0.10.2-6-g49f6