mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-18 21:22:49 +02:00
554 lines
18 KiB
PHP
554 lines
18 KiB
PHP
{%mainunit carbonwsextctrls.pas}
|
|
|
|
type
|
|
{ TCDCocoaTrayIcon }
|
|
|
|
TCDCocoaTrayIcon = objcclass(NSObject)
|
|
public
|
|
{ Fields }
|
|
LCLTrayIcon: TCustomTrayIcon;
|
|
bar: NSStatusBar;
|
|
item: NSStatusItem;
|
|
WSBitmap: TCocoaBitmap;//image: NSImage;
|
|
menu: NSMenu;
|
|
EmptyMenuTitle: CFStringRef;
|
|
(* // The following lists store the items and are used
|
|
// to be able to release them in ReleaseMenu
|
|
//
|
|
// SubMenuOwners: Holds all internal owners of the submenus
|
|
// SubMenuItems: Holds all items in submenus
|
|
SubMenuOwners: array of NSMenu;
|
|
SubMenuItems: array of NSMenuItem;
|
|
SubMenuImages: array of NSImage;
|
|
{ Structural Methods }
|
|
constructor Create; override;
|
|
destructor Destroy; override;
|
|
class function getClass: lobjc.id; override;
|
|
procedure AddMethods; override;
|
|
{ Pascal Methods }
|
|
function TrimAllChar(const S: string; const ch: Char): string;
|
|
function CreateMenu(APopUpMenu: TPopUpMenu): NSMenu;
|
|
function RecursiveCreateMenuItems(AMenuItem: TMenuItem;
|
|
ACallbackName: string; ACallbackClass: NSObject): NSMenuItem;
|
|
function CreateMenuItem(AMenuItem: TMenuItem;
|
|
ACallbackName: string; ACallbackClass: NSObject): NSMenuItem;
|
|
procedure ReleaseMenu();
|
|
procedure RemoveIcon();*)
|
|
function ConvertTIconToWSBitmap(AIcon: TIcon): TCocoaBitmap; message 'converticon:';
|
|
function ConvertTBitmapToWSBitmap(ABitmap: TBitmap): TCocoaBitmap; message 'convertbitmap:';
|
|
(* function IsMenuVisible: Boolean;
|
|
{ Objective-C compatible methods }
|
|
class procedure HandleMenuItemClick(_self: lobjc.id; _cmd: SEL; sender: lobjc.id); cdecl; //static;
|
|
class procedure HandleMenuWillOpen(_self: lobjc.id; _cmd: SEL; sender: lobjc.id); cdecl; //static;
|
|
class procedure HandleMenuDidClose(_self: lobjc.id; _cmd: SEL; sender: lobjc.id); cdecl; //static;*)
|
|
end;
|
|
|
|
(*const
|
|
Str_TPrivateCocoaCarbonTrayIcon = 'TTrayIcon';
|
|
|
|
Str_HandleMenuItemClick = 'HandleMenuItemClick';
|
|
Str_HandleMenuWillOpen = 'menuWillOpen:';
|
|
Str_HandleMenuDidClose = 'menuDidClose:';
|
|
|
|
{ TPrivateCocoaCarbonTrayIcon }
|
|
|
|
{@@
|
|
Adds methods to the class
|
|
|
|
Details of the parameters string:
|
|
|
|
The first parameter is the result (v = void),
|
|
followed by self and _cmd (@ = id and : = SEL),
|
|
and on the end "sender" (@ = id)
|
|
}
|
|
procedure TPrivateCocoaCarbonTrayIcon.AddMethods;
|
|
begin
|
|
AddMethod(Str_HandleMenuItemClick, 'v@:@', Pointer(HandleMenuItemClick));
|
|
AddMethod(Str_HandleMenuWillOpen, 'v@:@', Pointer(HandleMenuWillOpen));
|
|
AddMethod(Str_HandleMenuDidClose, 'v@:@', Pointer(HandleMenuDidClose));
|
|
end;
|
|
|
|
constructor TPrivateCocoaCarbonTrayIcon.Create;
|
|
begin
|
|
{ The class is registered on the Objective-C runtime before the NSObject constructor is called }
|
|
// The original plan was to create a descendent class, but causes wierd crashes
|
|
// so now we just stuck our method into NSObject
|
|
// if not CreateClassDefinition(Str_TPrivateCocoaCarbonTrayIcon, Str_NSObject) then WriteLn('Failed to create lobjc class');
|
|
|
|
EmptyMenuTitle := CFStringCreateWithPascalString(nil, '', kCFStringEncodingUTF8);
|
|
|
|
inherited Create;
|
|
end;
|
|
|
|
destructor TPrivateCocoaCarbonTrayIcon.Destroy;
|
|
begin
|
|
CFRelease(EmptyMenuTitle);
|
|
|
|
RemoveIcon();
|
|
ReleaseMenu();
|
|
|
|
if item <> nil then
|
|
begin
|
|
item.setImage(nil);
|
|
item.Free;
|
|
item := nil;
|
|
end;
|
|
|
|
if image <> nil then
|
|
begin
|
|
image.Free;
|
|
image := nil;
|
|
end;
|
|
|
|
inherited Destroy;
|
|
end;
|
|
|
|
class function TPrivateCocoaCarbonTrayIcon.getClass: lobjc.id;
|
|
begin
|
|
Result := objc_getClass({Str_TPrivateCocoaCarbonTrayIcon} Str_NSObject);
|
|
end;
|
|
|
|
{Removes/replaces all occurences of a character from a string}
|
|
function TPrivateCocoaCarbonTrayIcon.TrimAllChar(const S: string; const ch: Char): string;
|
|
var
|
|
buf: string;
|
|
begin
|
|
buf := S;
|
|
Result := '';
|
|
{while Pos finds a blank}
|
|
while (Pos(ch, buf) > 0) do
|
|
begin
|
|
{copy the substrings before the blank in to Result}
|
|
Result := Result + Copy(buf, 1, Pos(ch, buf) - 1);
|
|
buf := Copy(buf, Pos(ch, buf) + 1, Length(buf) - Pos(ch, buf));
|
|
end;
|
|
{There will still be a remainder in buf, so copy remainder into Result}
|
|
Result := Result + buf;
|
|
end;
|
|
|
|
{ Creates a NSMenu structure representing a TPopUpMenu }
|
|
function TPrivateCocoaCarbonTrayIcon.CreateMenu(APopUpMenu: TPopUpMenu): NSMenu;
|
|
var
|
|
i: Integer;
|
|
Item: NSMenuItem;
|
|
begin
|
|
Result := NSMenu.initWithTitle(EmptyMenuTitle);
|
|
// Result.setVersion(0);
|
|
Result.setDelegate(Self.Handle);
|
|
Result.setAutoenablesItems(LongBool(NO)); // For menu enabling/disabling
|
|
|
|
for i := 0 to APopUpMenu.Items.Count - 1 do
|
|
begin
|
|
{ If the submenu has a submenu it needs special treatment }
|
|
if APopUpMenu.Items[i].Count > 0 then
|
|
Item := RecursiveCreateMenuItems(APopUpMenu.Items[i], Str_HandleMenuItemClick, Self)
|
|
else
|
|
Item := CreateMenuItem(APopUpMenu.Items[i], Str_HandleMenuItemClick, Self);
|
|
|
|
if item <> nil then
|
|
Result.addItem(Item.Handle);
|
|
end;
|
|
end;
|
|
|
|
function TPrivateCocoaCarbonTrayIcon.RecursiveCreateMenuItems(
|
|
AMenuItem: TMenuItem; ACallbackName: string; ACallbackClass: NSObject): NSMenuItem;
|
|
var
|
|
j, subindex: Integer;
|
|
InternalOwner: NSMenu;
|
|
SubItem: NSMenuItem;
|
|
begin
|
|
// First create the menu
|
|
Result := CreateMenuItem(AMenuItem, Str_HandleMenuItemClick, Self);
|
|
|
|
// Then a owner for the children
|
|
InternalOwner := NSMenu.initWithTitle(EmptyMenuTitle);
|
|
InternalOwner.setAutoenablesItems(LongBool(NO)); // For menu enabling/disabling
|
|
|
|
subindex := Length(SubMenuOwners);
|
|
SetLength(SubMenuOwners, subindex + 1);
|
|
SubMenuOwners[subindex] := InternalOwner;
|
|
|
|
{ Add all submenus in this submenu }
|
|
for j := 0 to AMenuItem.Count - 1 do
|
|
begin
|
|
if AMenuItem.Items[j].Count > 0 then
|
|
SubItem := RecursiveCreateMenuItems(AMenuItem.Items[j], Str_HandleMenuItemClick, Self)
|
|
else
|
|
SubItem := CreateMenuItem(AMenuItem.Items[j], Str_HandleMenuItemClick, Self);
|
|
|
|
if SubItem <> nil then
|
|
InternalOwner.addItem(SubItem.Handle);
|
|
end;
|
|
|
|
// And set the submenu to the item
|
|
Result.setSubmenu(InternalOwner.Handle);
|
|
end;
|
|
|
|
function TPrivateCocoaCarbonTrayIcon.CreateMenuItem(AMenuItem: TMenuItem;
|
|
ACallbackName: string; ACallbackClass: NSObject): NSMenuItem;
|
|
var
|
|
ItemText: CFStringRef;
|
|
KeyText: CFStringRef;
|
|
subitemindex: Integer;
|
|
subimageindex: Integer;
|
|
AImage: NSImage;
|
|
StrBuffer: string;
|
|
// Default property implementation (=bold)
|
|
FontManager: NSFontManager;
|
|
AttrString: NSAttributedString;
|
|
AttrStringFont: NSFont;
|
|
AttrDictionary: NSDictionary;
|
|
begin
|
|
Result := nil;
|
|
|
|
{ Check visibility, invisible menus are implemented by not adding them at all,
|
|
because NSMenuItem.setHidden was only added in Mac OS X 10.5 }
|
|
if not AMenuItem.Visible then Exit;
|
|
|
|
{ The MenuItem is a separator }
|
|
if AMenuItem.Caption = '-' then
|
|
begin
|
|
Result := NSMenuItem.separatorItem();
|
|
end
|
|
{ A normal menu item }
|
|
else
|
|
begin
|
|
{ While creating the menus we ignore the & shortcut identifiers }
|
|
StrBuffer := TrimAllChar(AMenuItem.Caption, '&');
|
|
KeyText := CFStringCreateWithPascalString(nil, '', kCFStringEncodingUTF8);
|
|
ItemText := CFStringCreateWithPascalString(nil, StrBuffer, kCFStringEncodingUTF8);
|
|
{$ifdef VerboseCarbonTrayIcon}
|
|
WriteLn(' ItemText: ', IntToHex(Int64(ItemText), 8), ' ATitle: ', AMenuItem.Caption);
|
|
{$endif}
|
|
|
|
Result := NSMenuItem.initWithTitle_action_keyEquivalent(ItemText, nil, KeyText);
|
|
|
|
{ Assign the OnClick event handler }
|
|
Result.setTarget(ACallbackClass.Handle);
|
|
Result.setAction(sel_registerName(PChar(ACallbackName)));
|
|
|
|
{ Assign the checked state }
|
|
if AMenuItem.Checked then Result.setState(NSOnState)
|
|
else Result.setState(NSOffState);
|
|
|
|
{ Assign default (=bold) state }
|
|
if AMenuItem.Default then
|
|
begin
|
|
FontManager := NSFontManager.sharedFontManager;
|
|
// For now hard-code the menu font to 14, because the default size
|
|
// is 13, which is wrong, and looks bad.
|
|
AttrStringFont := NSFont.menuFontOfSize(14); // 0 = default size
|
|
AttrStringFont.Handle := FontManager.convertFont_toHaveTrait_(AttrStringFont.Handle, NSBoldFontMask);
|
|
AttrDictionary := NSDictionary.dictionaryWithObject_forKey(AttrStringFont.Handle, lobjc.id(NSFontAttributeName));
|
|
AttrString := NSAttributedString.initWithString_attributes(ItemText, CFDictionaryRef(AttrDictionary.Handle));
|
|
if AttrString.Handle <> nil then
|
|
Result.setAttributedTitle(AttrString.Handle);
|
|
|
|
// Only objects acquired with routines with alloc,
|
|
// init or copy in the name should be manually released
|
|
AttrString.Free;
|
|
AttrDictionary.Handle := nil;
|
|
AttrDictionary.Free;
|
|
AttrStringFont.Handle := nil;
|
|
AttrStringFont.Free;
|
|
FontManager.Handle := nil;
|
|
FontManager.Free;
|
|
end;
|
|
|
|
{ Assign enabled/disabled state }
|
|
if AMenuItem.Enabled then Result.setEnabled(LongBool(YES))
|
|
else Result.setEnabled(LongBool(NO));
|
|
|
|
{ Assign the item image, if any }
|
|
if (AMenuItem.Bitmap <> nil) and (not AMenuItem.Bitmap.Empty) then
|
|
begin
|
|
AImage := ConvertTBitmapToNSImage(AMenuItem.Bitmap);
|
|
Result.setImage(AImage.Handle);
|
|
|
|
// We also need to free the images
|
|
subimageindex := Length(SubMenuImages);
|
|
SetLength(SubMenuImages, subimageindex + 1);
|
|
SubMenuImages[subimageindex] := AImage;
|
|
end;
|
|
|
|
{ We use the Tag to hold the LCL MenuItem
|
|
RepresentedObject was also tried, by it crashed.
|
|
Cocoa probably tryes to use it as a real Cocoa object }
|
|
Result.setTag(PtrInt(AMenuItem));
|
|
|
|
{ Never add separators to the list of items to be freed }
|
|
subitemindex := Length(SubMenuItems);
|
|
SetLength(SubMenuItems, subitemindex + 1);
|
|
SubMenuItems[subitemindex] := Result;
|
|
end;
|
|
end;
|
|
|
|
procedure TPrivateCocoaCarbonTrayIcon.ReleaseMenu();
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := 0 to Length(SubMenuOwners) - 1 do
|
|
if SubMenuOwners[i] <> nil then SubMenuOwners[i].Free;
|
|
for i := 0 to Length(SubMenuItems) - 1 do
|
|
if (SubMenuItems[i] <> nil) then SubMenuItems[i].Free;
|
|
for i := 0 to Length(SubMenuImages) - 1 do
|
|
if (SubMenuImages[i] <> nil) then SubMenuImages[i].Free;
|
|
|
|
SetLength(SubMenuOwners, 0);
|
|
SetLength(SubMenuItems, 0);
|
|
SetLength(SubMenuImages, 0);
|
|
|
|
if item <> nil then
|
|
item.setMenu(nil);
|
|
|
|
if menu <> nil then
|
|
begin
|
|
menu.Free;
|
|
menu := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure TPrivateCocoaCarbonTrayIcon.RemoveIcon();
|
|
begin
|
|
if item <> nil then
|
|
bar.removeStatusItem(item.Handle);
|
|
end;*)
|
|
|
|
function TCDCocoaTrayIcon.ConvertTIconToWSBitmap(AIcon: TIcon): TCocoaBitmap;
|
|
(*var
|
|
ASize: NSSize;
|
|
ACGRect: CGRect;
|
|
AcurrentContext: NSGraphicsContext;*)
|
|
begin
|
|
Result := nil;
|
|
|
|
(* if (AIcon = nil) or (AIcon.Empty) then Exit;
|
|
|
|
{ Convert our CFImageRef to a NSImage }
|
|
|
|
ASize.width := TCarbonBitmap(AIcon.Handle).Width;
|
|
ASize.height := TCarbonBitmap(AIcon.Handle).Height;
|
|
ACGRect.size.width := ASize.width;
|
|
ACGRect.size.height := ASize.height;
|
|
ACGRect.origin.x := 0;
|
|
ACGRect.origin.y := 0;
|
|
|
|
Result := NSImage.initWithSize(ASize);
|
|
Result.setCacheMode(NSImageCacheNever);
|
|
Result.lockFocus;
|
|
AcurrentContext := NSGraphicsContext.currentContext();
|
|
CGContextDrawImage(AcurrentContext.graphicsPort, ACGRect, TCarbonBitmap(AIcon.Handle).CGImage);
|
|
{$ifdef VerboseCarbonTrayIcon}
|
|
WriteLn('::[TCarbonWSCustomTrayIcon.Show]',
|
|
' AcurrentContext ', IntToHex(PtrUInt(Pointer(AcurrentContext)), 8),
|
|
' AcurrentContext.ClassID ', IntToHex(Int64(AcurrentContext.ClassID), 8),
|
|
' AcurrentContext.Handle ', IntToHex(Int64(AcurrentContext.Handle), 8),
|
|
' AcurrentContext.graphicsPort ', IntToHex(Int64(AcurrentContext.graphicsPort), 8)
|
|
);
|
|
{$endif VerboseCarbonTrayIcon}
|
|
Result.unlockFocus;*)
|
|
end;
|
|
|
|
function TCDCocoaTrayIcon.ConvertTBitmapToWSBitmap(ABitmap: TBitmap): TCocoaBitmap;
|
|
(*var
|
|
ASize: NSSize;
|
|
ACGRect: CGRect;
|
|
AcurrentContext: NSGraphicsContext;*)
|
|
begin
|
|
Result := nil;
|
|
|
|
(* if (ABitmap = nil) or (ABitmap.Empty) then Exit;
|
|
|
|
{ Convert our CFImageRef to a NSImage }
|
|
|
|
ASize.width := TCarbonBitmap(ABitmap.Handle).Width;
|
|
ASize.height := TCarbonBitmap(ABitmap.Handle).Height;
|
|
ACGRect.size.width := ASize.width;
|
|
ACGRect.size.height := ASize.height;
|
|
ACGRect.origin.x := 0;
|
|
ACGRect.origin.y := 0;
|
|
|
|
Result := NSImage.initWithSize(ASize);
|
|
Result.setCacheMode(NSImageCacheNever);
|
|
Result.lockFocus;
|
|
AcurrentContext := NSGraphicsContext.currentContext();
|
|
CGContextDrawImage(AcurrentContext.graphicsPort, ACGRect, TCarbonBitmap(ABitmap.Handle).CGImage);
|
|
{$ifdef VerboseCarbonTrayIcon}
|
|
WriteLn('::[TCarbonWSCustomTrayIcon.Show]',
|
|
' AcurrentContext ', IntToHex(PtrUInt(Pointer(AcurrentContext)), 8),
|
|
' AcurrentContext.ClassID ', IntToHex(Int64(AcurrentContext.ClassID), 8),
|
|
' AcurrentContext.Handle ', IntToHex(Int64(AcurrentContext.Handle), 8),
|
|
' AcurrentContext.graphicsPort ', IntToHex(Int64(AcurrentContext.graphicsPort), 8)
|
|
);
|
|
{$endif VerboseCarbonTrayIcon}
|
|
Result.unlockFocus;*)
|
|
end;
|
|
|
|
(*// Using private APIs might cause a rejection in the Apple AppStore
|
|
// See: http://bugs.freepascal.org/view.php?id=19025
|
|
// But on the other hand there is no other way to check if the menu is visible
|
|
// http://www.cocoabuilder.com/archive/cocoa/100570-checking-if-menu-is-visible.html
|
|
{$ifdef CarbonUsePrivateAPIs}
|
|
function _NSGetCarbonMenu(AMenu: lobjc.id {NSMenu}): MenuRef; cdecl; external name '_NSGetCarbonMenu';
|
|
{$endif}
|
|
|
|
function TPrivateCocoaCarbonTrayIcon.IsMenuVisible: Boolean;
|
|
{$ifdef CarbonUsePrivateAPIs}
|
|
var
|
|
CarbonMenu: MenuRef;
|
|
theMenuTrackingData: MenuTrackingData;
|
|
begin
|
|
Result := False;
|
|
|
|
if menu = nil then Exit;
|
|
|
|
CarbonMenu := _NSGetCarbonMenu(menu.Handle);
|
|
if CarbonMenu = nil then Exit;
|
|
|
|
Result := GetMenuTrackingData(CarbonMenu, theMenuTrackingData) = noErr;
|
|
end;
|
|
{$else}
|
|
begin
|
|
Result := False;
|
|
end;
|
|
{$endif}
|
|
|
|
{ Here we try to get the LCL MenuItem from the Tag and then call
|
|
it's OnClick method }
|
|
class procedure TPrivateCocoaCarbonTrayIcon.HandleMenuItemClick(_self: lobjc.id;
|
|
_cmd: SEL; sender: lobjc.id); cdecl; //static;
|
|
var
|
|
AMenuItem: NSMenuItem;
|
|
LCLMenu: TMenuItem;
|
|
begin
|
|
AMenuItem := NSMenuItem.CreateWithHandle(lobjc.id(_cmd));
|
|
LCLMenu := TMenuItem(PtrInt(AMenuItem.Tag()));
|
|
if (LCLMenu <> nil) and Assigned(LCLMenu.OnClick) then LCLMenu.OnClick(LCLMenu);
|
|
end;
|
|
|
|
class procedure TPrivateCocoaCarbonTrayIcon.HandleMenuWillOpen(_self: lobjc.id;
|
|
_cmd: SEL; sender: lobjc.id); cdecl; //static;
|
|
var
|
|
AMenu: NSMenu;
|
|
//LCLMenu: TPopUpMenu;
|
|
begin
|
|
AMenu := NSMenu.CreateWithHandle(sender);
|
|
if AMenu=nil then ;
|
|
// LCLMenu := TPopUpMenu(PtrInt(AMenu.menuRepresentation()));
|
|
// if (LCLMenu <> nil) and Assigned(LCLMenu.OnPopUp) then LCLMenu.OnPopUp(LCLMenu);
|
|
end;
|
|
|
|
class procedure TPrivateCocoaCarbonTrayIcon.HandleMenuDidClose(_self: lobjc.id;
|
|
_cmd: SEL; sender: lobjc.id); cdecl; //static;
|
|
var
|
|
AMenu: NSMenu;
|
|
//LCLMenu: TPopUpMenu;
|
|
begin
|
|
AMenu := NSMenu.CreateWithHandle(sender);
|
|
// LCLMenu := TPopUpMenu(PtrInt(AMenu.menuRepresentation()));
|
|
// if (LCLMenu <> nil) and Assigned(LCLMenu.OnClose) then LCLMenu.OnClose(LCLMenu);
|
|
end;*)
|
|
|
|
{ TCarbonWSCustomTrayIcon }
|
|
|
|
class function TCDWSCustomTrayIcon.Hide(const ATrayIcon: TCustomTrayIcon): Boolean;
|
|
begin
|
|
Result := True;
|
|
end;
|
|
|
|
class function TCDWSCustomTrayIcon.Show(const ATrayIcon: TCustomTrayIcon): Boolean;
|
|
var
|
|
ATrayIconHandle: TCDCocoaTrayIcon;
|
|
begin
|
|
{$ifdef VerboseCDTrayIcon}
|
|
DebugLn(':>[TCarbonWSCustomTrayIcon.Show]');
|
|
{$endif VerboseCDTrayIcon}
|
|
|
|
Result := False;
|
|
|
|
{ Creates the handle }
|
|
|
|
ATrayIconHandle := TCDCocoaTrayIcon.alloc.init;
|
|
ATrayIconHandle.bar := NSStatusBar.systemStatusBar();
|
|
ATrayIconHandle.LCLTrayIcon := ATrayIcon;
|
|
ATrayIcon.Handle := HWND(ATrayIconHandle);
|
|
|
|
{ Converts the icon to NSImage }
|
|
|
|
ATrayIconHandle.WSBitmap := ATrayIconHandle.ConvertTIconToWSBitmap(ATrayIcon.Icon);
|
|
|
|
{ Shows the icon }
|
|
|
|
if ATrayIconHandle.item <> nil then Exit(True);
|
|
|
|
ATrayIconHandle.item := ATrayIconHandle.bar.statusItemWithLength(NSSquareStatusItemLength);
|
|
ATrayIconHandle.item.retain();
|
|
if Assigned(ATrayIconHandle.WSBitmap) and Assigned(ATrayIconHandle.WSBitmap.image) then
|
|
ATrayIconHandle.item.setImage(ATrayIconHandle.WSBitmap.image);
|
|
ATrayIconHandle.item.setHighlightMode(True);
|
|
|
|
(* { Inserts the menu }
|
|
|
|
if ATrayIcon.PopUpMenu <> nil then
|
|
begin
|
|
APrivateTrayIcon.menu := APrivateTrayIcon.CreateMenu(ATrayIcon.PopUpMenu);
|
|
if APrivateTrayIcon.item <> nil then
|
|
APrivateTrayIcon.item.setMenu(APrivateTrayIcon.menu.Handle);
|
|
end;*)
|
|
|
|
Result := True;
|
|
|
|
(* {$ifdef VerboseCDTrayIcon}
|
|
WriteLn(':<[TCarbonWSCustomTrayIcon.Show]',
|
|
' Handle: ', IntToHex(ATrayIcon.Handle, 8),
|
|
' ACGRect.size.width: ', ACGRect.size.width,
|
|
' ACGRect.size.height: ', ACGRect.size.height,
|
|
' ACGRect.origin.x: ', ACGRect.origin.x,
|
|
' ACGRect.origin.y: ', ACGRect.origin.y,
|
|
' TCarbonBitmap(ATrayIcon.Icon.Handle).CGImage ', IntToHex(Int64(TCarbonBitmap(ATrayIcon.Icon.Handle).CGImage), 8)
|
|
);
|
|
{$endif VerboseCDTrayIcon}*)
|
|
end;
|
|
|
|
class procedure TCDWSCustomTrayIcon.InternalUpdate(const ATrayIcon: TCustomTrayIcon);
|
|
begin
|
|
(* APrivateTrayIcon := TPrivateCocoaCarbonTrayIcon(ATrayIcon.Handle);
|
|
|
|
if APrivateTrayIcon = nil then Exit;
|
|
|
|
// The update is only necessary for a visible TTrayIcon
|
|
if not ATrayIcon.Visible then Exit;
|
|
|
|
{ Updates the image }
|
|
|
|
if Assigned(APrivateTrayIcon.Image) then
|
|
APrivateTrayIcon.image.Free;
|
|
|
|
if Assigned(ATrayIcon.Icon) then
|
|
begin
|
|
APrivateTrayIcon.image := APrivateTrayIcon.ConvertTIconToNSImage(ATrayIcon.Icon);
|
|
APrivateTrayIcon.item.setImage(APrivateTrayIcon.image.Handle);
|
|
end;
|
|
|
|
{ Inserts the menu }
|
|
|
|
APrivateTrayIcon.ReleaseMenu();
|
|
if ATrayIcon.PopUpMenu <> nil then
|
|
begin
|
|
APrivateTrayIcon.menu := APrivateTrayIcon.CreateMenu(ATrayIcon.PopUpMenu);
|
|
if APrivateTrayIcon.item <> nil then
|
|
APrivateTrayIcon.item.setMenu(APrivateTrayIcon.menu.Handle);
|
|
end;*)
|
|
end;
|
|
|
|
class function TCDWSCustomTrayIcon.ShowBalloonHint(const ATrayIcon: TCustomTrayIcon): Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
class function TCDWSCustomTrayIcon.GetPosition(const ATrayIcon: TCustomTrayIcon): Types.TPoint;
|
|
begin
|
|
Result := Types.Point(0, 0);
|
|
end;
|
|
|