Recent

Author Topic: Anyone have any sample code to use the Mac notification center such as Banner?  (Read 22633 times)

vonskie

  • Full Member
  • ***
  • Posts: 184
Okay this is far as I can get I am stuck anyone want to add to this or fix it.. Please.

Code: [Select]
{ Parsed from Foundation.framework (MacOSX10.8) NSUserNotification.h }
{ Created on Fri Mar 21 17:48:09 2014 }
unit UserNotification;

{$mode objfpc}{$H+}
{$modeswitch objectivec1}
 
interface
 
{$linkframework AppKit}
 
uses
  Classes, SysUtils, CocoaAll, MacOSAll, CarbonProc;

 
{$ifdef TYPES}

type
  NSUserNotificationPtr = ^NSUserNotification;
  NSUserNotificationCenterPtr = ^NSUserNotificationCenter;
  NSUserNotificationCenterDelegateProtocolPtr = ^NSUserNotificationCenterDelegateProtocol;
{$endif}

{$ifdef TYPES}
type
  NSUserNotificationActivationType = NSInteger;
  NSUserNotificationActivationTypePtr = ^NSUserNotificationActivationType;

const
  NSUserNotificationActivationTypeNone = 0;
  NSUserNotificationActivationTypeContentsClicked = 1;
  NSUserNotificationActivationTypeActionButtonClicked = 2;
{$endif}

{$ifdef CLASSES}


type

{NSUserNotification}

  NSUserNotification = objcclass external (NSObject, NSCopyingProtocol)
  private
    _internal: id;
  public
    procedure setTitle(newValue: NSString); message 'setTitle:';
    function title: NSString; message 'title';
    procedure setSubtitle(newValue: NSString); message 'setSubtitle:';
    function subtitle: NSString; message 'subtitle';
    procedure setInformativeText(newValue: NSString); message 'setInformativeText:';
    function informativeText: NSString; message 'informativeText';
    procedure setActionButtonTitle(newValue: NSString); message 'setActionButtonTitle:';
    function actionButtonTitle: NSString; message 'actionButtonTitle';
    procedure setUserInfo(newValue: NSDictionary); message 'setUserInfo:';
    function userInfo: NSDictionary; message 'userInfo';
    procedure setDeliveryDate(newValue: NSDate); message 'setDeliveryDate:';
    function deliveryDate: NSDate; message 'deliveryDate';
    procedure setDeliveryTimeZone(newValue: NSTimeZone); message 'setDeliveryTimeZone:';
    function deliveryTimeZone: NSTimeZone; message 'deliveryTimeZone';
    procedure setDeliveryRepeatInterval(newValue: NSDateComponents); message 'setDeliveryRepeatInterval:';
    function deliveryRepeatInterval: NSDateComponents; message 'deliveryRepeatInterval';
    function actualDeliveryDate: NSDate; message 'actualDeliveryDate';
    function isPresented: boolean; message 'isPresented';
    function isRemote: boolean; message 'isRemote';
    procedure setSoundName(newValue: NSString); message 'setSoundName:';
    function soundName: NSString; message 'soundName';
    procedure setHasActionButton(newValue: boolean); message 'setHasActionButton:';
    function hasActionButton: boolean; message 'hasActionButton';
    function activationType: NSUserNotificationActivationType; message 'activationType';
    procedure setOtherButtonTitle(newValue: NSString); message 'setOtherButtonTitle:';
    function otherButtonTitle: NSString; message 'otherButtonTitle';

    { Adopted protocols }
    function copyWithZone (zone: NSZonePtr): id; message 'copyWithZone:';
  end;
{$endif}

{$ifdef EXTERNAL_SYMBOLS}
var
  NSUserNotificationDefaultSoundName: NSString { available in 10_8, NA }; cvar; external;
{$endif}

{$ifdef CLASSES}

type
  NSUserNotificationCenter = objcclass external (NSObject)
  private
    _internal: id;
  public
    class function defaultUserNotificationCenter: NSUserNotificationCenter; message 'defaultUserNotificationCenter';
    procedure setDelegate(newValue: NSUserNotificationCenterDelegateProtocol); message 'setDelegate:';
    function delegate: NSUserNotificationCenterDelegateProtocol; message 'delegate';
    procedure setScheduledNotifications(newValue: NSArray); message 'setScheduledNotifications:';
    function scheduledNotifications: NSArray; message 'scheduledNotifications';
    procedure scheduleNotification (notification: NSUserNotification); message 'scheduleNotification:';
    procedure removeScheduledNotification (notification: NSUserNotification); message 'removeScheduledNotification:';
    function deliveredNotifications: NSArray; message 'deliveredNotifications';
    procedure deliverNotification (notification: NSUserNotification); message 'deliverNotification:';
    procedure removeDeliveredNotification (notification: NSUserNotification); message 'removeDeliveredNotification:';
    procedure removeAllDeliveredNotifications; message 'removeAllDeliveredNotifications';
  end;
{$endif}

{$ifdef PROTOCOLS}

type
  NSUserNotificationCenterDelegateProtocol = objcprotocol external name 'NSUserNotificationCenterDelegate' (NSObjectProtocol)
  optional
    procedure userNotificationCenter_didDeliverNotification (center: NSUserNotificationCenter; notification: NSUserNotification); message 'userNotificationCenter:didDeliverNotification:';
    procedure userNotificationCenter_didActivateNotification (center: NSUserNotificationCenter; notification: NSUserNotification); message 'userNotificationCenter:didActivateNotification:';
    function userNotificationCenter_shouldPresentNotification (center: NSUserNotificationCenter; notification: NSUserNotification): boolean; message 'userNotificationCenter:shouldPresentNotification:';
  end;
{$endif}



« Last Edit: March 22, 2014, 03:28:56 am by skalogryz »

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Okay this is far as I can get I am stuck anyone want to add to this or fix it.. Please.
you can go further. ... but, what is the exact problem?
btw, try to change {$linkframework AppKit} to {$linkframework Foundation}


My exposure to free pascal is about 30 days so there is much I do not understand.
Lol, you pushed an application live, it's too late to make excuses!

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
any luck?

vonskie

  • Full Member
  • ***
  • Posts: 184

exodusd

  • New member
  • *
  • Posts: 9
Hi,

since I was also looking for a way to use the Mac OS X user notifications, I took the code you posted and tried to get it running. I've removed the ifdefs, because if I understand that correctly, they are for inclusion in the CocoaAll unit (they are defined there when other files are included). I've also commented out the "copyWithZone" stuff, because I got a "duplicate symbol" error. Unfortunately I have no clue about the Cocoa stuff or the details of how it is integrated in fpc/lazarus, so I just commented it out.  ;)

Anyway, I've added two procedures called DeliverUserNotification that you can use to show a user notification with title, subtitle, message and (optionally) sound. The procedure without the sound parameter will play the default sound - if you want a notification without sound, then just call the other one and pass an empty string for the sound parameter.

Cheers,
  Robert


Code: [Select]
unit UserNotification;

{$mode objfpc}{$H+}
{$modeswitch objectivec1}

interface

{$linkframework Foundation}

uses
  Classes, SysUtils, CocoaAll, CarbonProc;

const
  NSUserNotificationActivationTypeNone = 0;
  NSUserNotificationActivationTypeContentsClicked = 1;
  NSUserNotificationActivationTypeActionButtonClicked = 2;

type
  NSUserNotificationPtr = ^NSUserNotification;
  NSUserNotificationCenterPtr = ^NSUserNotificationCenter;
  NSUserNotificationCenterDelegateProtocolPtr = ^NSUserNotificationCenterDelegateProtocol;

  NSUserNotificationActivationType = NSInteger;
  NSUserNotificationActivationTypePtr = ^NSUserNotificationActivationType;

  //NSUserNotification = objcclass external (NSObject, NSCopyingProtocol)
  NSUserNotification = objcclass external (NSObject)
  private
    _internal: id;
  public
    procedure setTitle(newValue: NSString); message 'setTitle:';
    function title: NSString; message 'title';
    procedure setSubtitle(newValue: NSString); message 'setSubtitle:';
    function subtitle: NSString; message 'subtitle';
    procedure setInformativeText(newValue: NSString); message 'setInformativeText:';
    function informativeText: NSString; message 'informativeText';
    procedure setActionButtonTitle(newValue: NSString); message 'setActionButtonTitle:';
    function actionButtonTitle: NSString; message 'actionButtonTitle';
    procedure setUserInfo(newValue: NSDictionary); message 'setUserInfo:';
    function userInfo: NSDictionary; message 'userInfo';
    procedure setDeliveryDate(newValue: NSDate); message 'setDeliveryDate:';
    function deliveryDate: NSDate; message 'deliveryDate';
    procedure setDeliveryTimeZone(newValue: NSTimeZone); message 'setDeliveryTimeZone:';
    function deliveryTimeZone: NSTimeZone; message 'deliveryTimeZone';
    procedure setDeliveryRepeatInterval(newValue: NSDateComponents); message 'setDeliveryRepeatInterval:';
    function deliveryRepeatInterval: NSDateComponents; message 'deliveryRepeatInterval';
    function actualDeliveryDate: NSDate; message 'actualDeliveryDate';
    function isPresented: boolean; message 'isPresented';
    function isRemote: boolean; message 'isRemote';
    procedure setSoundName(newValue: NSString); message 'setSoundName:';
    function soundName: NSString; message 'soundName';
    procedure setHasActionButton(newValue: boolean); message 'setHasActionButton:';
    function hasActionButton: boolean; message 'hasActionButton';
    function activationType: NSUserNotificationActivationType; message 'activationType';
    procedure setOtherButtonTitle(newValue: NSString); message 'setOtherButtonTitle:';
    function otherButtonTitle: NSString; message 'otherButtonTitle';

    // Adopted protocols
    //function copyWithZone (zone: NSZonePtr): id; message 'copyWithZone:';
  end;

  NSUserNotificationCenterDelegateProtocol = objcprotocol;

  NSUserNotificationCenter = objcclass external (NSObject)
  private
    _internal: id;
  public
    class function defaultUserNotificationCenter: NSUserNotificationCenter; message 'defaultUserNotificationCenter';
    procedure setDelegate(newValue: NSUserNotificationCenterDelegateProtocol); message 'setDelegate:';
    function delegate: NSUserNotificationCenterDelegateProtocol; message 'delegate';
    procedure setScheduledNotifications(newValue: NSArray); message 'setScheduledNotifications:';
    function scheduledNotifications: NSArray; message 'scheduledNotifications';
    procedure scheduleNotification (notification: NSUserNotification); message 'scheduleNotification:';
    procedure removeScheduledNotification (notification: NSUserNotification); message 'removeScheduledNotification:';
    function deliveredNotifications: NSArray; message 'deliveredNotifications';
    procedure deliverNotification (notification: NSUserNotification); message 'deliverNotification:';
    procedure removeDeliveredNotification (notification: NSUserNotification); message 'removeDeliveredNotification:';
    procedure removeAllDeliveredNotifications; message 'removeAllDeliveredNotifications';
  end;

  NSUserNotificationCenterDelegateProtocol = objcprotocol external name 'NSUserNotificationCenterDelegate' (NSObjectProtocol)
  optional
    procedure userNotificationCenter_didDeliverNotification (center: NSUserNotificationCenter; notification: NSUserNotification); message 'userNotificationCenter:didDeliverNotification:';
    procedure userNotificationCenter_didActivateNotification (center: NSUserNotificationCenter; notification: NSUserNotification); message 'userNotificationCenter:didActivateNotification:';
    function userNotificationCenter_shouldPresentNotification (center: NSUserNotificationCenter; notification: NSUserNotification): boolean; message 'userNotificationCenter:shouldPresentNotification:';
  end;

procedure DeliverUserNotification(const Title, Subtitle, Message: string);
procedure DeliverUserNotification(const Title, Subtitle, Message, Sound: string);

var
  NSUserNotificationDefaultSoundName: NSString { available in 10_8, NA }; cvar; external;

implementation

procedure DeliverUserNotification(const Title, Subtitle, Message: string);
var
  Notification: NSUserNotification;

begin
  Notification := NSUserNotification.alloc.init;

  try
    Notification.setTitle(NSStr(PChar(Title)));
    Notification.setSubtitle(NSStr(PChar(Subtitle)));
    Notification.setInformativeText(NSStr(PChar(Message)));
    Notification.setSoundName(NSUserNotificationDefaultSoundName);
    NSUserNotificationCenter.defaultUserNotificationCenter.deliverNotification(Notification);

  finally
    Notification.release;
  end;
end;



procedure DeliverUserNotification(const Title, Subtitle, Message, Sound: string);
var
  Notification: NSUserNotification;

begin
  Notification := NSUserNotification.alloc.init;

  try
    Notification.setTitle(NSStr(PChar(Title)));
    Notification.setSubtitle(NSStr(PChar(Subtitle)));
    Notification.setInformativeText(NSStr(PChar(Message)));

    if Sound <> '' then
      Notification.setSoundName(NSStr(PChar(Sound)));

    NSUserNotificationCenter.defaultUserNotificationCenter.deliverNotification(Notification);

  finally
    Notification.release;
  end;
end;



end.
« Last Edit: May 05, 2014, 12:00:54 pm by exodusd »

exodusd

  • New member
  • *
  • Posts: 9
I just noticed some charset problems with that code. Here's a modified version using NSString(CFStringCreateWithPascalString(kCFAllocatorDefault, Str, kCFStringEncodingUTF8)) for the pascal to NSString conversion. I got that from a different example and it seems to do the trick.

I'm not sure if there's an easier way to deal with this, but at least this one seems to work:

Code: [Select]
unit UserNotification;

interface

{$mode objfpc}{$H+}
{$modeswitch objectivec1}
{$linkframework Foundation}

uses
  Classes, SysUtils, MacOSAll, CocoaAll, CarbonProc;

const
  NSUserNotificationActivationTypeNone = 0;
  NSUserNotificationActivationTypeContentsClicked = 1;
  NSUserNotificationActivationTypeActionButtonClicked = 2;

type
  NSUserNotificationPtr = ^NSUserNotification;
  NSUserNotificationCenterPtr = ^NSUserNotificationCenter;
  NSUserNotificationCenterDelegateProtocolPtr = ^NSUserNotificationCenterDelegateProtocol;

  NSUserNotificationActivationType = NSInteger;
  NSUserNotificationActivationTypePtr = ^NSUserNotificationActivationType;

  //NSUserNotification = objcclass external (NSObject, NSCopyingProtocol)
  NSUserNotification = objcclass external (NSObject)
  private
    _internal: id;
  public
    procedure setTitle(newValue: NSString); message 'setTitle:';
    function title: NSString; message 'title';
    procedure setSubtitle(newValue: NSString); message 'setSubtitle:';
    function subtitle: NSString; message 'subtitle';
    procedure setInformativeText(newValue: NSString); message 'setInformativeText:';
    function informativeText: NSString; message 'informativeText';
    procedure setActionButtonTitle(newValue: NSString); message 'setActionButtonTitle:';
    function actionButtonTitle: NSString; message 'actionButtonTitle';
    procedure setUserInfo(newValue: NSDictionary); message 'setUserInfo:';
    function userInfo: NSDictionary; message 'userInfo';
    procedure setDeliveryDate(newValue: NSDate); message 'setDeliveryDate:';
    function deliveryDate: NSDate; message 'deliveryDate';
    procedure setDeliveryTimeZone(newValue: NSTimeZone); message 'setDeliveryTimeZone:';
    function deliveryTimeZone: NSTimeZone; message 'deliveryTimeZone';
    procedure setDeliveryRepeatInterval(newValue: NSDateComponents); message 'setDeliveryRepeatInterval:';
    function deliveryRepeatInterval: NSDateComponents; message 'deliveryRepeatInterval';
    function actualDeliveryDate: NSDate; message 'actualDeliveryDate';
    function isPresented: boolean; message 'isPresented';
    function isRemote: boolean; message 'isRemote';
    procedure setSoundName(newValue: NSString); message 'setSoundName:';
    function soundName: NSString; message 'soundName';
    procedure setHasActionButton(newValue: boolean); message 'setHasActionButton:';
    function hasActionButton: boolean; message 'hasActionButton';
    function activationType: NSUserNotificationActivationType; message 'activationType';
    procedure setOtherButtonTitle(newValue: NSString); message 'setOtherButtonTitle:';
    function otherButtonTitle: NSString; message 'otherButtonTitle';

    // Adopted protocols
    //function copyWithZone (zone: NSZonePtr): id; message 'copyWithZone:';
  end;

  NSUserNotificationCenterDelegateProtocol = objcprotocol;

  NSUserNotificationCenter = objcclass external (NSObject)
  private
    _internal: id;
  public
    class function defaultUserNotificationCenter: NSUserNotificationCenter; message 'defaultUserNotificationCenter';
    procedure setDelegate(newValue: NSUserNotificationCenterDelegateProtocol); message 'setDelegate:';
    function delegate: NSUserNotificationCenterDelegateProtocol; message 'delegate';
    procedure setScheduledNotifications(newValue: NSArray); message 'setScheduledNotifications:';
    function scheduledNotifications: NSArray; message 'scheduledNotifications';
    procedure scheduleNotification (notification: NSUserNotification); message 'scheduleNotification:';
    procedure removeScheduledNotification (notification: NSUserNotification); message 'removeScheduledNotification:';
    function deliveredNotifications: NSArray; message 'deliveredNotifications';
    procedure deliverNotification (notification: NSUserNotification); message 'deliverNotification:';
    procedure removeDeliveredNotification (notification: NSUserNotification); message 'removeDeliveredNotification:';
    procedure removeAllDeliveredNotifications; message 'removeAllDeliveredNotifications';
  end;

  NSUserNotificationCenterDelegateProtocol = objcprotocol external name 'NSUserNotificationCenterDelegate' (NSObjectProtocol)
  optional
    procedure userNotificationCenter_didDeliverNotification (center: NSUserNotificationCenter; notification: NSUserNotification); message 'userNotificationCenter:didDeliverNotification:';
    procedure userNotificationCenter_didActivateNotification (center: NSUserNotificationCenter; notification: NSUserNotification); message 'userNotificationCenter:didActivateNotification:';
    function userNotificationCenter_shouldPresentNotification (center: NSUserNotificationCenter; notification: NSUserNotification): boolean; message 'userNotificationCenter:shouldPresentNotification:';
  end;

procedure DeliverUserNotification(const Title, Subtitle, Message: string);
procedure DeliverUserNotification(const Title, Subtitle, Message, Sound: string);

var
  NSUserNotificationDefaultSoundName: NSString { available in 10_8, NA }; cvar; external;

implementation

procedure DeliverUserNotification(const Title, Subtitle, Message: string);
begin
  DeliverUserNotification(Title, Subtitle, Message, CFStringToStr(CFStringRef(NSUserNotificationDefaultSoundName)));
end;



procedure DeliverUserNotification(const Title, Subtitle, Message, Sound: string);
var
  Notification: NSUserNotification;
  TmpNSStr: NSString;

begin
  Notification := NSUserNotification.alloc.init;

  try
    TmpNSStr := NSString(CFStringCreateWithPascalString(kCFAllocatorDefault, Title, kCFStringEncodingUTF8));

    try
      Notification.setTitle(TmpNSStr);

    finally
      TmpNSStr.release;
    end;

    TmpNSStr := NSString(CFStringCreateWithPascalString(kCFAllocatorDefault, Subtitle, kCFStringEncodingUTF8));

    try
      Notification.setSubtitle(TmpNSStr);

    finally
      TmpNSStr.release;
    end;

    TmpNSStr := NSString(CFStringCreateWithPascalString(kCFAllocatorDefault, Message, kCFStringEncodingUTF8));

    try
      Notification.setInformativeText(TmpNSStr);

    finally
      TmpNSStr.release;
    end;

    if Sound <> '' then
    begin
      TmpNSStr := NSString(CFStringCreateWithPascalString(kCFAllocatorDefault, Sound, kCFStringEncodingUTF8));

      try
        Notification.setSoundName(TmpNSStr);

      finally
        TmpNSStr.release;
      end;
    end;

    NSUserNotificationCenter.defaultUserNotificationCenter.deliverNotification(Notification);

  finally
    Notification.release;
  end;
end;



end.
« Last Edit: May 05, 2014, 10:59:02 pm by exodusd »

esvignolo

  • Full Member
  • ***
  • Posts: 159
  • Using FPC in Windows, Linux, Macos
Thanks exodusd, work well, but by default is not showing the popup, i search and found this:

http://blog.mahasoftware.com/post/28968246552/how-to-use-the-10-8-notification-center-api

By default, Notification Center only displays notifications if the application is not frontmost. To always present the notification, you need to set the delegate on the NSUserNotificationCenter as shown above, and implement the NSUserNotification

CenterDelegate as follows:

- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification
{
    return YES;
}


Can you add this to your unit?

Thanks again

exodusd

  • New member
  • *
  • Posts: 9
Ok, it took a while to figure this out. I took some inspiration from this wiki: http://wiki.lazarus.freepascal.org/Mac_OS_X_Text-to-Speech and read a bit about the delegates. I finally got it to work, but it would be great if someone with more experience could test this for memory leaks etc in Mac OS X, since I mostly put together code without really understanding what I'm doing. I tried using release for each alloc.init, but I lack the experience to know whether this is the right way to do it. ;)

Anyway, here's the code I came up with. I added some ifdefs to make sure that the unit is empty for other platforms than Mac OS X (Darwin), so that you can add it to crossplatform programs without running into any problems (as long as you're using the code only on Mac OS X - e.g. as a replacement for the TrayIcon baloon-tips - that's what I'm using it for).

Cheers,
  Robert

Code: [Select]
unit UserNotification;

interface

{$ifdef Darwin}
{$mode objfpc}{$H+}
{$modeswitch objectivec1}
{$linkframework Foundation}

uses
  Classes, SysUtils, MacOSAll, CocoaAll, CarbonProc;



const
  NSUserNotificationActivationTypeNone = 0;
  NSUserNotificationActivationTypeContentsClicked = 1;
  NSUserNotificationActivationTypeActionButtonClicked = 2;



type
  NSUserNotificationPtr = ^NSUserNotification;
  NSUserNotificationCenterPtr = ^NSUserNotificationCenter;
  NSUserNotificationCenterDelegateProtocolPtr = ^NSUserNotificationCenterDelegateProtocol;

  NSUserNotificationActivationType = NSInteger;
  NSUserNotificationActivationTypePtr = ^NSUserNotificationActivationType;



  //NSUserNotification = objcclass external (NSObject, NSCopyingProtocol)
  NSUserNotification = objcclass external (NSObject)
  private
    _internal: id;
  public
    procedure setTitle(newValue: NSString); message 'setTitle:';
    function title: NSString; message 'title';
    procedure setSubtitle(newValue: NSString); message 'setSubtitle:';
    function subtitle: NSString; message 'subtitle';
    procedure setInformativeText(newValue: NSString); message 'setInformativeText:';
    function informativeText: NSString; message 'informativeText';
    procedure setActionButtonTitle(newValue: NSString); message 'setActionButtonTitle:';
    function actionButtonTitle: NSString; message 'actionButtonTitle';
    procedure setUserInfo(newValue: NSDictionary); message 'setUserInfo:';
    function userInfo: NSDictionary; message 'userInfo';
    procedure setDeliveryDate(newValue: NSDate); message 'setDeliveryDate:';
    function deliveryDate: NSDate; message 'deliveryDate';
    procedure setDeliveryTimeZone(newValue: NSTimeZone); message 'setDeliveryTimeZone:';
    function deliveryTimeZone: NSTimeZone; message 'deliveryTimeZone';
    procedure setDeliveryRepeatInterval(newValue: NSDateComponents); message 'setDeliveryRepeatInterval:';
    function deliveryRepeatInterval: NSDateComponents; message 'deliveryRepeatInterval';
    function actualDeliveryDate: NSDate; message 'actualDeliveryDate';
    function isPresented: boolean; message 'isPresented';
    function isRemote: boolean; message 'isRemote';
    procedure setSoundName(newValue: NSString); message 'setSoundName:';
    function soundName: NSString; message 'soundName';
    procedure setHasActionButton(newValue: boolean); message 'setHasActionButton:';
    function hasActionButton: boolean; message 'hasActionButton';
    function activationType: NSUserNotificationActivationType; message 'activationType';
    procedure setOtherButtonTitle(newValue: NSString); message 'setOtherButtonTitle:';
    function otherButtonTitle: NSString; message 'otherButtonTitle';

    // Adopted protocols
    //function copyWithZone (zone: NSZonePtr): id; message 'copyWithZone:';
  end;



  NSUserNotificationCenterDelegateProtocol = objcprotocol;



  NSUserNotificationCenter = objcclass external (NSObject)
  private
    _internal: id;
  public
    class function defaultUserNotificationCenter: NSUserNotificationCenter; message 'defaultUserNotificationCenter';
    //procedure setDelegate(newValue: NSUserNotificationCenterDelegateProtocol); message 'setDelegate:';
    procedure setDelegate(newValue: NSObject); message 'setDelegate:';
    function delegate: NSUserNotificationCenterDelegateProtocol; message 'delegate';
    procedure setScheduledNotifications(newValue: NSArray); message 'setScheduledNotifications:';
    function scheduledNotifications: NSArray; message 'scheduledNotifications';
    procedure scheduleNotification (notification: NSUserNotification); message 'scheduleNotification:';
    procedure removeScheduledNotification (notification: NSUserNotification); message 'removeScheduledNotification:';
    function deliveredNotifications: NSArray; message 'deliveredNotifications';
    procedure deliverNotification (notification: NSUserNotification); message 'deliverNotification:';
    procedure removeDeliveredNotification (notification: NSUserNotification); message 'removeDeliveredNotification:';
    procedure removeAllDeliveredNotifications; message 'removeAllDeliveredNotifications';
  end;



  NSUserNotificationCenterDelegateProtocol = objcprotocol external name 'NSUserNotificationCenterDelegate' (NSObjectProtocol)
  optional
    procedure userNotificationCenter_didDeliverNotification (center: NSUserNotificationCenter; notification: NSUserNotification); message 'userNotificationCenter:didDeliverNotification:';
    procedure userNotificationCenter_didActivateNotification (center: NSUserNotificationCenter; notification: NSUserNotification); message 'userNotificationCenter:didActivateNotification:';
    function userNotificationCenter_shouldPresentNotification (center: NSUserNotificationCenter; notification: NSUserNotification): boolean; message 'userNotificationCenter:shouldPresentNotification:';
  end;



  NSUserNotificationCenterAlwaysShowDelegate = objcclass(NSObject)
  public
    function shouldPresentNotification ({%H-}center: NSUserNotificationCenter; {%H-}notification: NSUserNotification): boolean; message 'userNotificationCenter:shouldPresentNotification:';
  end;



procedure DeliverUserNotification(const Title, Subtitle, Message: string);
procedure DeliverUserNotification(const Title, Subtitle, Message, Sound: string);



var
  NSUserNotificationDefaultSoundName: NSString { available in 10_8, NA }; cvar; external;

{$endif}

implementation

{$ifdef Darwin}

var
  UserNotificationCenterDelegate: NSUserNotificationCenterAlwaysShowDelegate;



function NSUserNotificationCenterAlwaysShowDelegate.shouldPresentNotification (center: NSUserNotificationCenter; notification: NSUserNotification): boolean;
begin
  Result := True;
end;



procedure DeliverUserNotification(const Title, Subtitle, Message: string);
begin
  DeliverUserNotification(Title, Subtitle, Message, CFStringToStr(CFStringRef(NSUserNotificationDefaultSoundName)));
end;



procedure DeliverUserNotification(const Title, Subtitle, Message, Sound: string);
var
  Notification: NSUserNotification;
  TmpNSStr: NSString;

begin
  Notification := NSUserNotification.alloc.init;

  try
    TmpNSStr := NSString(CFStringCreateWithPascalString(kCFAllocatorDefault, Title, kCFStringEncodingUTF8));

    try
      Notification.setTitle(TmpNSStr);

    finally
      TmpNSStr.release;
    end;

    TmpNSStr := NSString(CFStringCreateWithPascalString(kCFAllocatorDefault, Subtitle, kCFStringEncodingUTF8));

    try
      Notification.setSubtitle(TmpNSStr);

    finally
      TmpNSStr.release;
    end;

    TmpNSStr := NSString(CFStringCreateWithPascalString(kCFAllocatorDefault, Message, kCFStringEncodingUTF8));

    try
      Notification.setInformativeText(TmpNSStr);

    finally
      TmpNSStr.release;
    end;

    if Sound <> '' then
    begin
      TmpNSStr := NSString(CFStringCreateWithPascalString(kCFAllocatorDefault, Sound, kCFStringEncodingUTF8));

      try
        Notification.setSoundName(TmpNSStr);

      finally
        TmpNSStr.release;
      end;
    end;

    NSUserNotificationCenter.defaultUserNotificationCenter.deliverNotification(Notification);

  finally
    Notification.release;
  end;
end;



initialization
  UserNotificationCenterDelegate := NSUserNotificationCenterAlwaysShowDelegate.alloc.init;
  NSUserNotificationCenter.defaultUserNotificationCenter.setDelegate(UserNotificationCenterDelegate);



finalization
  NSUserNotificationCenter.defaultUserNotificationCenter.setDelegate(nil);
  UserNotificationCenterDelegate.release;

{$endif}



end.

esvignolo

  • Full Member
  • ***
  • Posts: 159
  • Using FPC in Windows, Linux, Macos
Thanks!!!! work fine!!!  :D :D :D :D :D :D

Hansaplast

  • Hero Member
  • *****
  • Posts: 674
  • Tweaking4All.com
    • Tweaking4All
I realize this topic is old, but I assume others may stumble on this one as well.
It seems that "NSUserNotification" is deprecated (source).


Maybe it's an idea to update TPopupNotifier to accommodate these kind of "new" notifications for macOS (link), Windows (link), Growl, LibNotify (link), and whatever is out there (using the current TPopupNotifier as a fall back).

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2020
  • Former Delphi 1-7, 10.2 user
Maybe it's an idea to update TPopupNotifier to accommodate these kind of "new" notifications for macOS (link)

Your macOS link leads to the Core Foundation UserNotification object which is for use in processes that do not otherwise have user interfaces, but may need occasional interaction with the user.

The new-fangled method which replaced NSUserNotifications deprecated in Mojave is the UserNotifications Framework which debuted in Mojave. Not that Apple made it easy to find... and this despite a documentation bug being lodged in November 2018.

dbannon

  • Hero Member
  • *****
  • Posts: 2786
    • tomboy-ng, a rewrite of the classic Tomboy
Maybe it's an idea to update TPopupNotifier to accommodate these kind of "new" notifications for macOS (link), Windows (link), Growl, LibNotify (link), and whatever is out there (using the current TPopupNotifier as a fall back).

Wow, Hansaplast, what a great observation !  I just tried the Linux link you suggested, the code is nine years old but works perfectly.  Will try the Windows one noting Trev's comment about Mac (its always Mac isn't it ?).   Anyway, if libnotify is as widely installed as I suspect it might be, it will appear in my next release, Linux version, and I will play with a wrapper to try the others. Its is so much better than TPopupNotify, I tend to use a Showmessage() where I can just because it looks a bit better.

If 'we' decide to get a cross platform thing going, should it be built into TPopupNotifier or be a new thing ?  TPopupNotifier does not time out itself and setting libnotify to not time out is unreliable so someone may find its a different behaviour.  And 'different' might be a problem ....

Anyway, really good point Hansaplast, brilliant on Linux at least !

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

Hansaplast

  • Hero Member
  • *****
  • Posts: 674
  • Tweaking4All.com
    • Tweaking4All
@Trev:
Thanks for the link to the UserNotifications Framework link.
Good info: I had not seen that one before.


@dbannon:
I made my own poor mans edition of cross platform notifications.
It's not done very well, especially on the Windows side its not great.
For macOS and Linux it works. But as Trev mentioned: the macOS method is already deprecated.
The Linux method actually works great, and won't give any trouble if libnotify isn't installed.
For Windows I use my home-brew notification (not great).


So, yeah I'd be open to either improve TPopupNotify, but we'd still need an elegant implementation for macOS and Windows.

dbannon

  • Hero Member
  • *****
  • Posts: 2786
    • tomboy-ng, a rewrite of the classic Tomboy
......
So, yeah I'd be open to either improve TPopupNotify, but we'd still need an elegant implementation for macOS and Windows.

The trouble would be that we would have to add a "time out" setting to TPopupNotify that defaults to infinity. And current fashion says it should be as short as possible.  But still needs to be done.

Hmm....

D

Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

 

TinyPortal © 2005-2018