Lazarus

Programming => Operating Systems => macOS / Mac OS X => Topic started by: Hansaplast on November 22, 2020, 04:26:09 pm

Title: [SOLVED] Big Sur - Fix for automatically adjusting TrayIcon to menubar color
Post by: Hansaplast on November 22, 2020, 04:26:09 pm


With Big Sur, one can no longer rely on dark vs light theme to determine if an TrayIcon should be using light or dark colors.
The system wide menubar is by default transparent and the color and type of wallpaper influences if the background turns out to be light or dark.


After a long search I found that the image of a trayicon (NSStatusItem?) can have an option to do this automatically by using the setTemplate function of the image to true. When doing this, macOS will automatically adjust a transparent icon with only black pixels.


This can be activated relatively easy by adding a single line to the file lazarus/lcl/interfaces/cocoa/cocoatrayicon.inc and simply setting the image to a "template".


In cocoatrayicon.inc add the following line to the lclSetTrayIcon procedure:


Code: Pascal  [Select][+][-]
  1. image.setTemplate(true);


I've added it below to the if (ATrayIcon.icon <> nil) section (line 14):


Code: Pascal  [Select][+][-]
  1. procedure TCocoaStatusItemHandle.lclSetTrayIcon(ATrayIcon: TCustomTrayIcon);
  2. var
  3.   image: NSImage;
  4. begin
  5.   TrayIcon := ATrayIcon;
  6.  
  7.  
  8.   // Shows the icon
  9.  
  10.  
  11.   if (ATrayIcon.icon <> nil) and (ATrayIcon.icon.Handle <> 0) then
  12.   begin
  13.     image := TCocoaBitmap(ATrayIcon.icon.Handle).image;
  14.     image.setTemplate(true); // < --- added this line
  15.     if image <> nil then statusitem.setImage(image);
  16.   end;
  17.  
  18.  
  19.   // Show the menu
  20.  
  21.  
  22.   if (ATrayIcon.PopUpMenu <> nil) then
  23.   begin
  24.     ATrayIcon.PopUpMenu.HandleNeeded();
  25.     //ATrayIcon.PopUpMenu.
  26.     if Assigned(statusitem.menu) and (statusitem.menu.delegate = NSMenuDelegateProtocol(self)) then
  27.       statusitem.menu.setDelegate(nil);
  28.  
  29.  
  30.     statusitem.setMenu(TCocoaMenu(ATrayIcon.PopUpMenu.Handle));
  31.  
  32.  
  33.     TCocoaMenu(ATrayIcon.PopUpMenu.Handle).setDelegate( self);
  34.   end;
  35. end;



I've done some testing with this and this work great.


Downside: when using trayicons with multiple colors, this may result in not so pretty icons.


So my questions:


Since this only works well with transparent icons with black pixels, this may cause issues with multicolor icons.
So it is not safe to assume this is fine (even though it seems that macOS is steering towards simple icons like that), or is it?
Can we add this as a macOS-only option for the TTrayIcon? Or does anyone know how to override the TCocoaStatusItemHandle.lclSetTrayIcon procedure?
Title: Re: Big Sur - Fix for automatically adjusting TrayIcon to menubar color
Post by: Hansaplast on November 23, 2020, 01:07:17 pm

Maybe this is useful for others, if we do not wish to make this an option for TTrayIcon;


Code: Pascal  [Select][+][-]
  1. Uses ... CocoaGDIObjects ...;
  2.  
  3.  
  4. ...
  5.  
  6.   TForm1 = class(TForm)
  7.      ...
  8.      TrayIcon1: TTrayIcon;
  9.      ...
  10.   private
  11.  
  12.  
  13.   public
  14.  
  15.  
  16.   end;                              
  17.  
  18. ...
  19.  
  20. procedure TForm1.FormCreate(Sender: TObject);
  21. var
  22.   image: NSImage;
  23. begin
  24.   if Assigned(TrayIcon1.Icon) then
  25.     begin
  26.       image := TCocoaBitmap(TrayIcon1.icon.Handle).image;
  27.       image.setTemplate(true);
  28.       TrayIcon1.InternalUpdate;
  29.     end;
  30. end;
TinyPortal © 2005-2018