Cocoa: fix the issue of Notification on macOS 13+, issue #41016, Merge branch 'cocoa/notify'

This commit is contained in:
rich2014 2024-07-09 22:34:17 +08:00
parent 6b03d7c4dd
commit c11434dd55
4 changed files with 118 additions and 3 deletions

View File

@ -62,7 +62,74 @@ var
NSPasteboardTypeRuler: NSPasteboardType; cvar; external;
NSPasteboardTypeSound: NSPasteboardType; cvar; external;
const
UNAuthorizationOptionBadge = 1 shl 0;
UNAuthorizationOptionSound = 1 shl 1;
UNAuthorizationOptionAlert = 1 shl 2;
UNAuthorizationOptionCarPlay = 1 shl 3;
type
UNNotificationSound = objcclass external (NSObject)
class function defaultSound: UNNotificationSound; message 'defaultSound';
end;
UNNotificationContent = objcclass external (NSObject)
public
function title: NSString; message 'title';
function subtitle: NSString; message 'subtitle';
function body: NSString; message 'body';
function badge: NSNumber; message 'badge';
function sound: UNNotificationSound; message 'sound';
end;
UNMutableNotificationContent = objcclass external (UNNotificationContent)
public
procedure setTitle( newValue: NSString ); message 'setTitle:';
procedure setSubtitle( newValue: NSString ); message 'setSubtitle:';
procedure setBody( newValue: NSString ); message 'setBody:';
procedure setBadge( newValue: NSNumber ); message 'setBadge:';
procedure setSound( newValue: UNNotificationSound ); message 'setSound:';
end;
UNNotificationTrigger = objcclass external (NSObject)
public
function repeats: ObjCBool; message 'repeats';
end;
UNTimeIntervalNotificationTrigger = objcclass external (UNNotificationTrigger)
public
class function triggerWithTimeInterval_repeats(
timeInterval: NSTimeInterval; repeats_: ObjCBool ): id;
message 'triggerWithTimeInterval:repeats:';
end;
UNNotificationRequest = objcclass external (NSObject)
public
class function requestWithIdentifier_content_trigger(
identifier: NSString;
content: UNNotificationContent;
trigger: UNNotificationTrigger ): id;
message 'requestWithIdentifier:content:trigger:';
function identifier: NSString; message 'identifier';
function content: UNNotificationContent; message 'content';
function trigger: UNNotificationTrigger; message 'trigger';
end;
UNAuthorizationOptions = NSUInteger;
UNUserNotificationCenter = objcclass external (NSObject)
public
class function currentNotificationCenter: UNUserNotificationCenter;
message 'currentNotificationCenter';
procedure requestAuthorizationWithOptions_completionHandler(
options: UNAuthorizationOptions; completionHandler: OpaqueCBlock = nil );
message 'requestAuthorizationWithOptions:completionHandler:';
procedure addNotificationRequest_withCompletionHandler(
request: UNNotificationRequest;
completionHandler: OpaqueCBlock = nil );
message 'addNotificationRequest:withCompletionHandler:';
end;
NSMenuFix = objccategory external (NSMenu)
function itemAtIndex(index: NSInteger): NSMenuItem; message 'itemAtIndex:';
end;

View File

@ -154,15 +154,52 @@ begin
StatusItemHandle.lclSetTrayIcon(ATrayIcon);
end;
class function TCocoaWSCustomTrayIcon.ShowBalloonHint(const ATrayIcon: TCustomTrayIcon): Boolean;
// macOS 10.14+ required
// APP codesign required
// codesign --deep --force --verify --verbose --sign '-' 'your.app'
class function TCocoaWSCustomTrayIcon.newUserNotify(const ATrayIcon: TCustomTrayIcon): Boolean;
var
nc: UNUserNotificationCenter;
trigger: UNTimeIntervalNotificationTrigger;
message: UNMutableNotificationContent;
request: UNNotificationRequest;
const
options: NSInteger = UNAuthorizationOptionAlert or
UNAuthorizationOptionBadge or
UNAuthorizationOptionSound;
begin
Result:= True;
nc:= UNUserNotificationCenter.currentNotificationCenter;
nc.requestAuthorizationWithOptions_completionHandler( options );
trigger:= UNTimeIntervalNotificationTrigger.triggerWithTimeInterval_repeats(
0.01, False);
message:= UNMutableNotificationContent.new;
message.setTitle( StrToNSString(ATrayIcon.BalloonTitle) );
message.setBody( StrToNSString(ATrayIcon.BalloonHint) );
message.setSound( UNNotificationSound.defaultSound );
request:= UNNotificationRequest.requestWithIdentifier_content_trigger(
NSString.string_, message, trigger );
nc.addNotificationRequest_withCompletionHandler( request );
message.release;
end;
class function TCocoaWSCustomTrayIcon.legacyUserNotify(const ATrayIcon: TCustomTrayIcon): Boolean;
var
nc: NSUserNotificationCenter;
message: NSUserNotification;
begin
Result := True;
message:= NSUserNotification.alloc.init;
message:= NSUserNotification.new;
message.setTitle( StrToNSString(ATrayIcon.BalloonTitle) );
message.setInformativeText( StrToNSString(ATrayIcon.BalloonHint) );
if NOT NSApplication(NSApp).isActive then
message.setSoundName( NSUserNotificationDefaultSoundName );
nc:= NSUserNotificationCenter.defaultUserNotificationCenter;
if CocoaConfig.CocoaAlwaysPresentNotification then begin
@ -174,6 +211,14 @@ begin
message.release;
end;
class function TCocoaWSCustomTrayIcon.ShowBalloonHint(const ATrayIcon: TCustomTrayIcon): Boolean;
begin
if NSAppKitVersionNumber >= NSAppKitVersionNumber11_0 then
Result:= newUserNotify( ATrayIcon ) // APP codesign required
else
Result:= legacyUserNotify( ATrayIcon );
end;
class function TCocoaWSCustomTrayIcon.GetPosition(const ATrayIcon: TCustomTrayIcon): TPoint;
begin
Result := Point(0, 0);

View File

@ -174,6 +174,9 @@ type
{ TCocoaWSCustomTrayIcon }
TCocoaWSCustomTrayIcon = class(TWSCustomTrayIcon)
private
class function newUserNotify(const ATrayIcon: TCustomTrayIcon): Boolean;
class function legacyUserNotify(const ATrayIcon: TCustomTrayIcon): Boolean;
published
class function Hide(const ATrayIcon: TCustomTrayIcon): Boolean; override;
class function Show(const ATrayIcon: TCustomTrayIcon): Boolean; override;

View File

@ -83,7 +83,7 @@ if TargetOS='darwin' then begin
+' -framework OpenGL'
+' ''-dylib_file'' ''/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib''';
end else if LCLWidgetType='cocoa' then
UsageLinkerOptions := '-framework Cocoa';
UsageLinkerOptions := '-framework Cocoa -weak_framework UserNotifications';
end else if TargetOS='solaris' then begin
UsageLibraryPath:='/usr/X11R6/lib';
end;"/>