Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Native notifications for Windows, Linux and OSX #3389

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
22d8d98
!F Porting FreeDesktop NotificationManager from PR
pr8x Dec 22, 2019
4e58a51
!T Cleaning up the notification page
pr8x Dec 23, 2019
39ea180
!B Fixing About and Exit commands
pr8x Dec 23, 2019
964d28e
!F Adding support for Win10NotificationManager
pr8x Dec 23, 2019
fee7617
!F OSX Notification COM implementation
pr8x Dec 23, 2019
ba3f4b6
!F Adding CreateNotificationManager hook to IAvaloniaNativeFactory
pr8x Dec 24, 2019
9efd362
!F Implementing NativeNotificationManager
pr8x Dec 25, 2019
51b53a2
!T Reverting to .NET Core 2
pr8x Dec 27, 2019
291a274
Merge branch 'master' into native_notifications_win_linux_osx
pr8x Jan 12, 2020
d7463f1
Merge branch 'master' into native_notifications_win_linux_osx
danwalmsley Jan 22, 2020
da4422c
!T Reverting to ReactiveCommand
pr8x Jan 25, 2020
a4e3230
Merge branch 'master' into native_notifications_win_linux_osx
pr8x Jan 25, 2020
05ea283
!R Installing shortcut and appUserModlId in AfterSetup.
pr8x Jan 25, 2020
4c4e4ab
Merge branch 'native_notifications_win_linux_osx' of https://github.c…
pr8x Jan 25, 2020
70978d7
!R Making INotificationManager.Show async
pr8x Feb 1, 2020
e171730
Merge branch 'master' into native_notifications_win_linux_osx
pr8x Feb 1, 2020
8db0b4d
!R Using ValueTask
pr8x Feb 1, 2020
a937b2c
!T Don't create notifier every time notification is requested
pr8x Feb 1, 2020
7c76b26
!T Removing duplicate package
pr8x Feb 1, 2020
c9913df
!R Fallback to null when FreeDesktopNotificationManager fails to init…
pr8x Feb 1, 2020
625faf9
!R Moving AfterSetup() into Win32Platform
pr8x Feb 1, 2020
7323816
!T Removing service check
pr8x Feb 16, 2020
62d3953
Merge branch 'master' into native_notifications_win_linux_osx
pr8x Feb 16, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions native/Avalonia.Native/inc/avalonia-native.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct IAvnGlSurfaceRenderTarget;
struct IAvnGlSurfaceRenderingSession;
struct IAvnAppMenu;
struct IAvnAppMenuItem;
struct IAvnNotificationManager;

struct AvnSize
{
Expand Down Expand Up @@ -172,6 +173,17 @@ enum AvnWindowEdge
WindowEdgeSouthEast
};


typedef void (*AvnNotificationActionCallback)(int);
typedef void (*AvnNotificationCloseCallback)(int);

struct AvnNotification {
int identifier;
const char* TitleUtf8;
const char* TextUtf8;
int durationMs;
};

AVNCOM(IAvaloniaNativeFactory, 01) : IUnknown
{
public:
Expand All @@ -190,6 +202,7 @@ AVNCOM(IAvaloniaNativeFactory, 01) : IUnknown
virtual HRESULT CreateMenu (IAvnAppMenu** ppv) = 0;
virtual HRESULT CreateMenuItem (IAvnAppMenuItem** ppv) = 0;
virtual HRESULT CreateMenuItemSeperator (IAvnAppMenuItem** ppv) = 0;
virtual HRESULT CreateNotificationManager(IAvnNotificationManager** ppv) = 0;
};

AVNCOM(IAvnString, 17) : IUnknown
Expand Down Expand Up @@ -412,4 +425,11 @@ AVNCOM(IAvnAppMenuItem, 19) : IUnknown
virtual HRESULT SetAction (IAvnPredicateCallback* predicate, IAvnActionCallback* callback) = 0;
};

AVNCOM(IAvnNotificationManager, 20) : IUnknown
{
virtual void SetCloseCallback(AvnNotificationCloseCallback callback) = 0;
virtual void SetActionCallback(AvnNotificationActionCallback callback) = 0;
virtual bool ShowNotification(AvnNotification* notification) = 0;
};

extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative();
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
/* Begin PBXBuildFile section */
1A002B9E232135EE00021753 /* app.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A002B9D232135EE00021753 /* app.mm */; };
37155CE4233C00EB0034DCE9 /* menu.h in Headers */ = {isa = PBXBuildFile; fileRef = 37155CE3233C00EB0034DCE9 /* menu.h */; };
37A517B32159597E00FBA241 /* Screens.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37A517B22159597E00FBA241 /* Screens.mm */; };
37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37C09D8721580FE4006A6758 /* SystemDialogs.mm */; };
37DDA9B0219330F8002E132B /* AvnString.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37DDA9AF219330F8002E132B /* AvnString.mm */; };
37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37E2330E21583241000CB7E2 /* KeyTransform.mm */; };
37A517B32159597E00FBA241 /* screens.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37A517B22159597E00FBA241 /* screens.mm */; };
37C09D8821580FE4006A6758 /* system_dialogs.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37C09D8721580FE4006A6758 /* system_dialogs.mm */; };
37DDA9B0219330F8002E132B /* avnstring.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37DDA9AF219330F8002E132B /* avnstring.mm */; };
37E2330F21583241000CB7E2 /* key_transform.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37E2330E21583241000CB7E2 /* key_transform.mm */; };
520624B322973F4100C4DCEF /* menu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 520624B222973F4100C4DCEF /* menu.mm */; };
5B21A982216530F500CEE36E /* cursor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B21A981216530F500CEE36E /* cursor.mm */; };
5B8BD94F215BFEA6005ED2A7 /* clipboard.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */; };
Expand All @@ -22,19 +22,21 @@
AB661C1E2148230F00291242 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB661C1D2148230F00291242 /* AppKit.framework */; };
AB661C202148286E00291242 /* window.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB661C1F2148286E00291242 /* window.mm */; };
AB8F7D6B21482D7F0057DBA5 /* platformthreading.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */; };
FA60D81023B2D993006DCFA0 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA60D80F23B2D992006DCFA0 /* Cocoa.framework */; };
FA7E93B823B10CE0004F99B3 /* notification_manager.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA7E93B723B10CE0004F99B3 /* notification_manager.mm */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
1A002B9D232135EE00021753 /* app.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = app.mm; sourceTree = "<group>"; };
37155CE3233C00EB0034DCE9 /* menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = menu.h; sourceTree = "<group>"; };
379860FE214DA0C000CD0246 /* KeyTransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyTransform.h; sourceTree = "<group>"; };
379860FE214DA0C000CD0246 /* key_transform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = key_transform.h; sourceTree = "<group>"; };
37A4E71A2178846A00EACBCD /* headers */ = {isa = PBXFileReference; lastKnownFileType = folder; name = headers; path = ../../inc; sourceTree = "<group>"; };
37A517B22159597E00FBA241 /* Screens.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Screens.mm; sourceTree = "<group>"; };
37C09D8721580FE4006A6758 /* SystemDialogs.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SystemDialogs.mm; sourceTree = "<group>"; };
37A517B22159597E00FBA241 /* screens.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = screens.mm; sourceTree = "<group>"; };
37C09D8721580FE4006A6758 /* system_dialogs.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = system_dialogs.mm; sourceTree = "<group>"; };
37C09D8A21581EF2006A6758 /* window.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = window.h; sourceTree = "<group>"; };
37DDA9AF219330F8002E132B /* AvnString.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AvnString.mm; sourceTree = "<group>"; };
37DDA9B121933371002E132B /* AvnString.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AvnString.h; sourceTree = "<group>"; };
37E2330E21583241000CB7E2 /* KeyTransform.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyTransform.mm; sourceTree = "<group>"; };
37DDA9AF219330F8002E132B /* avnstring.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = avnstring.mm; sourceTree = "<group>"; };
37DDA9B121933371002E132B /* avnstring.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = avnstring.h; sourceTree = "<group>"; };
37E2330E21583241000CB7E2 /* key_transform.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = key_transform.mm; sourceTree = "<group>"; };
520624B222973F4100C4DCEF /* menu.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = menu.mm; sourceTree = "<group>"; };
5B21A981216530F500CEE36E /* cursor.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = cursor.mm; sourceTree = "<group>"; };
5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = clipboard.mm; sourceTree = "<group>"; };
Expand All @@ -47,13 +49,16 @@
AB661C212148288600291242 /* common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = "<group>"; };
AB7A61EF2147C815003C5833 /* libAvalonia.Native.OSX.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libAvalonia.Native.OSX.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = platformthreading.mm; sourceTree = "<group>"; };
FA60D80F23B2D992006DCFA0 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
FA7E93B723B10CE0004F99B3 /* notification_manager.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = notification_manager.mm; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
AB7A61EC2147C814003C5833 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FA60D81023B2D993006DCFA0 /* Cocoa.framework in Frameworks */,
AB1E522C217613570091CD71 /* OpenGL.framework in Frameworks */,
AB661C1E2148230F00291242 /* AppKit.framework in Frameworks */,
);
Expand All @@ -65,6 +70,7 @@
AB661C1C2148230E00291242 /* Frameworks */ = {
isa = PBXGroup;
children = (
FA60D80F23B2D992006DCFA0 /* Cocoa.framework */,
AB1E522B217613570091CD71 /* OpenGL.framework */,
AB661C1D2148230F00291242 /* AppKit.framework */,
);
Expand All @@ -74,25 +80,26 @@
AB7A61E62147C814003C5833 = {
isa = PBXGroup;
children = (
FA7E93B723B10CE0004F99B3 /* notification_manager.mm */,
1A002B9D232135EE00021753 /* app.mm */,
37DDA9B121933371002E132B /* AvnString.h */,
37DDA9AF219330F8002E132B /* AvnString.mm */,
37DDA9B121933371002E132B /* avnstring.h */,
37DDA9AF219330F8002E132B /* avnstring.mm */,
37A4E71A2178846A00EACBCD /* headers */,
AB573DC3217605E400D389A2 /* gl.mm */,
5BF943652167AD1D009CAE35 /* cursor.h */,
5B21A981216530F500CEE36E /* cursor.mm */,
5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */,
AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */,
AB661C212148288600291242 /* common.h */,
379860FE214DA0C000CD0246 /* KeyTransform.h */,
37E2330E21583241000CB7E2 /* KeyTransform.mm */,
379860FE214DA0C000CD0246 /* key_transform.h */,
37E2330E21583241000CB7E2 /* key_transform.mm */,
AB661C1F2148286E00291242 /* window.mm */,
37C09D8A21581EF2006A6758 /* window.h */,
AB00E4F62147CA920032A60A /* main.mm */,
37155CE3233C00EB0034DCE9 /* menu.h */,
520624B222973F4100C4DCEF /* menu.mm */,
37A517B22159597E00FBA241 /* Screens.mm */,
37C09D8721580FE4006A6758 /* SystemDialogs.mm */,
37A517B22159597E00FBA241 /* screens.mm */,
37C09D8721580FE4006A6758 /* system_dialogs.mm */,
AB7A61F02147C815003C5833 /* Products */,
AB661C1C2148230E00291242 /* Frameworks */,
);
Expand Down Expand Up @@ -178,13 +185,14 @@
1A002B9E232135EE00021753 /* app.mm in Sources */,
5B8BD94F215BFEA6005ED2A7 /* clipboard.mm in Sources */,
5B21A982216530F500CEE36E /* cursor.mm in Sources */,
37DDA9B0219330F8002E132B /* AvnString.mm in Sources */,
37DDA9B0219330F8002E132B /* avnstring.mm in Sources */,
AB8F7D6B21482D7F0057DBA5 /* platformthreading.mm in Sources */,
37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */,
37E2330F21583241000CB7E2 /* key_transform.mm in Sources */,
FA7E93B823B10CE0004F99B3 /* notification_manager.mm in Sources */,
520624B322973F4100C4DCEF /* menu.mm in Sources */,
37A517B32159597E00FBA241 /* Screens.mm in Sources */,
37A517B32159597E00FBA241 /* screens.mm in Sources */,
AB00E4F72147CA920032A60A /* main.mm in Sources */,
37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */,
37C09D8821580FE4006A6758 /* system_dialogs.mm in Sources */,
AB573DC4217605E400D389A2 /* gl.mm in Sources */,
AB661C202148286E00291242 /* window.mm in Sources */,
);
Expand Down Expand Up @@ -242,9 +250,11 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
"INFOPLIST_FILE[sdk=*]" = "";
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.avalonia.native.osx;
SDKROOT = macosx;
};
name = Debug;
Expand Down Expand Up @@ -294,6 +304,7 @@
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_BUNDLE_IDENTIFIER = com.avalonia.native.osx;
SDKROOT = macosx;
};
name = Release;
Expand All @@ -305,6 +316,8 @@
DYLIB_CURRENT_VERSION = 1;
EXECUTABLE_PREFIX = lib;
HEADER_SEARCH_PATHS = ../../inc;
"INFOPLIST_FILE[sdk=*]" = "";
PRODUCT_BUNDLE_IDENTIFIER = com.avalonia.native.osx;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
Expand All @@ -316,6 +329,7 @@
DYLIB_CURRENT_VERSION = 1;
EXECUTABLE_PREFIX = lib;
HEADER_SEARCH_PATHS = ../../inc;
PRODUCT_BUNDLE_IDENTIFIER = com.avalonia.native.osx;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
Expand Down
35 changes: 35 additions & 0 deletions native/Avalonia.Native/src/OSX/app.mm
Original file line number Diff line number Diff line change
@@ -1,8 +1,39 @@
#include "common.h"
#include <Cocoa/Cocoa.h>
#import <objc/runtime.h>

@implementation NSBundle (FakeBundleIdentifier)

- (NSString *)__bundleIdentifier;
{
if (self == [NSBundle mainBundle]) {
return @"com.avalonia.native.osx";
Copy link
Member

@kekekeks kekekeks Feb 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add an option to configure that with AvaloniaNativeMacOptions and fall back to "com.avaloniaui.apps."+Assembly.GetEntryAssembly().Name

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably should also somehow interact with bundle identifier from Info.plist if the app is running from an actual app bundle.

Copy link
Contributor Author

@pr8x pr8x Feb 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we should check the [[NSBundle mainBundle] bundleIdentifier] and only install the fake bundle identifier when there is no mainBundle identifier.

} else {
return [self __bundleIdentifier];
}
}

@end

//It is required to install a bundle identifier in order to use the notification center.
//Otherwise [NSUserNotificationCenter defaultUserNotificationCenter] will be nil.
//https://github.com/munki/munki/blob/master/code/apps/munki-notifier/munki-notifier/AppDelegate.m
static BOOL InstallFakeBundleIdentifierHook()
{
Class classImpl = objc_getClass("NSBundle");
if (classImpl) {
method_exchangeImplementations(class_getInstanceMethod(classImpl, @selector(bundleIdentifier)),
class_getInstanceMethod(classImpl, @selector(__bundleIdentifier)));
return YES;
}
return NO;
}

@interface AvnAppDelegate : NSObject<NSApplicationDelegate>
@end

extern NSApplicationActivationPolicy AvnDesiredActivationPolicy = NSApplicationActivationPolicyRegular;

@implementation AvnAppDelegate
- (void)applicationWillFinishLaunching:(NSNotification *)notification
{
Expand All @@ -20,6 +51,10 @@ - (void)applicationWillFinishLaunching:(NSNotification *)notification
- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
[[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps];

@autoreleasepool {
InstallFakeBundleIdentifierHook();
}
}

@end
Expand Down
2 changes: 1 addition & 1 deletion native/Avalonia.Native/src/OSX/clipboard.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.

#include "common.h"
#include "AvnString.h"
#include "avnstring.h"

class Clipboard : public ComSingleObject<IAvnClipboard, &IID_IAvnClipboard>
{
Expand Down
1 change: 1 addition & 0 deletions native/Avalonia.Native/src/OSX/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ extern IAvnGlSurfaceRenderTarget* CreateGlRenderTarget(NSWindow* window, NSView*
extern IAvnAppMenu* CreateAppMenu();
extern IAvnAppMenuItem* CreateAppMenuItem();
extern IAvnAppMenuItem* CreateAppMenuItemSeperator();
extern IAvnNotificationManager* CreateNotificationManager();
extern void SetAppMenu (NSString* appName, IAvnAppMenu* appMenu);
extern IAvnAppMenu* GetAppMenu ();
extern NSMenuItem* GetAppMenuItem ();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.

#include "KeyTransform.h"
#include "key_transform.h"

const int kVK_ANSI_A = 0x00;
const int kVK_ANSI_S = 0x01;
Expand Down
6 changes: 6 additions & 0 deletions native/Avalonia.Native/src/OSX/main.mm
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,12 @@ virtual HRESULT ObtainAppMenu(IAvnAppMenu** retOut) override

return S_OK;
}

virtual HRESULT CreateNotificationManager(IAvnNotificationManager** ppv) override
{
*ppv = ::CreateNotificationManager();
return S_OK;
}
};

extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative()
Expand Down
83 changes: 83 additions & 0 deletions native/Avalonia.Native/src/OSX/notification_manager.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#include "common.h"
#import <Cocoa/Cocoa.h>

@interface NotificationCenterDelegate : NSObject<NSUserNotificationCenterDelegate>
@property AvnNotificationActionCallback ActionCallback;
@property AvnNotificationCloseCallback CloseCallback;
@end

@implementation NotificationCenterDelegate

- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification
{
// Force notifications to be always displayed even when running in foreground
return YES;
}

-(void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification
{
if (notification.activationType != NSUserNotificationActivationTypeContentsClicked &&
notification.activationType != NSUserNotificationActivationTypeActionButtonClicked) {
return;
}

[self ActionCallback]([notification.identifier intValue]);
}
@end

class NotificationManager : public ComSingleObject<IAvnNotificationManager, &IID_IAvnNotificationManager>
{
NotificationCenterDelegate* _notificationCenterDelegate;

public:
FORWARD_IUNKNOWN()

NotificationManager() {
_notificationCenterDelegate = [NotificationCenterDelegate new];
}

virtual bool ShowNotification(AvnNotification* notification) override {

NSUserNotificationCenter* notificationCenter = [NSUserNotificationCenter defaultUserNotificationCenter];
notificationCenter.delegate = _notificationCenterDelegate;

NSUserNotification* cocoaNotification = [NSUserNotification new];

int notificationId = notification->identifier;
cocoaNotification.identifier = [NSString stringWithFormat:@"%i", notificationId];
cocoaNotification.title = [NSString stringWithUTF8String:notification->TitleUtf8];
cocoaNotification.informativeText = [NSString stringWithUTF8String:notification->TextUtf8];

[notificationCenter deliverNotification:cocoaNotification];

if (notification->durationMs != 0) {
unsigned long long durationNs = notification->durationMs * NSEC_PER_MSEC;

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, durationNs), dispatch_get_main_queue(), ^{
[notificationCenter removeDeliveredNotification:cocoaNotification];

//TODO: HACK: I can't find a global close event... Might be missing something.
_notificationCenterDelegate.CloseCallback(notificationId);
});
}

return YES;
}

virtual void SetCloseCallback(AvnNotificationCloseCallback callback) override {
_notificationCenterDelegate.CloseCallback = callback;
}

virtual void SetActionCallback(AvnNotificationActionCallback callback) override {
_notificationCenterDelegate.ActionCallback = callback;
}

};

extern IAvnNotificationManager* CreateNotificationManager()
{
@autoreleasepool
{
return new NotificationManager();
}
}
2 changes: 1 addition & 1 deletion native/Avalonia.Native/src/OSX/platformthreading.mm
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ - (void) action
FORWARD_IUNKNOWN()
bool Running = false;
bool Cancelled = false;
virtual void Cancel()
virtual void Cancel() override
{
Cancelled = true;
if(Running)
Expand Down
2 changes: 1 addition & 1 deletion native/Avalonia.Native/src/OSX/window.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#include "common.h"
#include "window.h"
#include "KeyTransform.h"
#include "key_transform.h"
#include "cursor.h"
#include "menu.h"
#include <OpenGL/gl.h>
Expand Down
Loading