Difference between revisions of "Talk:How to use a TrayIcon"

From Free Pascal wiki
Jump to navigationJump to search
m (Fixed syntax highlighting)
 
(14 intermediate revisions by one other user not shown)
Line 2: Line 2:
  
 
== Linux Problems ==
 
== Linux Problems ==
=== Background ===
 
Recently, changes in some Linux Desktops have threatened the TrayIcon Lazarus Component. Apparently driven by concern that the Linux System Tray (of which the TrayIcon is an example) is being used in overly complicated User Interfaces and is too hard to maintain at the Desktop level. Some major players have disabled the System Tray altogether, some have replaced it with a simpler model and some still support it.
 
In summary, there are currently three ways that you will see and interact with what might be called a System Tray Icon -
 
* The old System Tray Model, as provided by Lazarus makes a small icon visible, a Left Click is passed to a click handler, a Right Click can invoke a popup menu.
 
* The Libappindicator3, seems to be based on the (late) Unity Desktop and work done by the KDE people, perhaps. In Lazarus, only shows the Icon if a Popup Menu is assigned and cannot invoke a Click Handler. So the only interaction possible is the Popup Menu.
 
* AppNotifier - apparently intended to be a replacement for SystemTray, works in most Distributions based on newer Desktops. Not supported in Lazarus.
 
  
=== State of Play ===
+
'''DRAFT prior to release of Lazarus 2.0.6'''
A programmer intending to use the Lazarus TrayIcon needs to consider how it will be used. What is possible depends on the Distribution and Desktop used. And remember, this is a dynamic situation, it will change.
 
* '''Providing a Popup Menu only.''' This mode may be best bet for a new design, seems likely it will work widely in the medium future. Use libappindicator3 and falls back to Old SystemTray if LibAppIndicator3 fails.  
 
* '''Catch Left Clicks'''  with or without a popup menu. This mode is best implemented by the Old System Tray model and won't work with newer releases of several major distributions (such as Ubuntu, RedHat and Suse) without a third party add on that may, or may not be available in the immediate future. My tests used TopIconsPlus but there are several similar Gnome Extensions. Note that an end user may be put off the process of installing and enabling these extensions. With each release of Gnome, frantic changes appear to be necessary with these TopIcons* extensions, so its possible some time lag may exist between a distro release and your application working. 
 
  
'''Old System Tray Mode'''
+
=== Background ===
 
+
Recently, changes in some Linux Desktops that use Gnome have threatened the TrayIcon Lazarus Component. Apparently driven by concern that the Linux System Tray (of which the TrayIcon is an example) is being used in overly complicated User Interfaces and is too hard to maintain at the Desktop level. Some major players have disabled the System Tray altogether, some have replaced it with a simpler model and some still support it.
* Things like TopIconsPlus are necessary with some Gnome based distros.
 
* Many Gnome3 based distros provide a startup model that uses XOrg Display Manager rather than Wayland. In some cases, this helps in situations where TopIconsPlus is active and under Wayland and menus appear in apparently random locations. Under XOrg, they again appear near the spot where user has clicked. But does not help in all cases (?).
 
* Seems hard or not possible to test if the call to initialize the TrayIcon has succeeded or not, so cannot have a fall back position.
 
  
'''The LibAppIndicator3 Mode'''
+
Most, if not all distributions that don't use Gnome Shell are not a problem. The Gnome Shell desktops, to be used with Lazarus's TrayIcon all require the Gnome Extension, TopIconsPlus or one of its peers be installed. This introduces some issues -
  
* You must assign a Popup Menu or the Tray Icon does not appear.
+
* End users are uncomfortable installing these Extensions but its unavoidable if they are using a Gnome distribution.
* The libappindicator3 model does not generate a LeftClick handler call. Users interaction is only via Popup Menu. This may be seen as complying with the Gnome Developers quest for simplifying the user interface (or maybe you think its dumbing it down !).
+
* libappindicator3 is used (and may also need be installed) and that provides a limited version of the System Tray, a left click is not passed through to TrayIcon1Click(), it can only be used to invoke a PopupMenu. Further, if a menu is not assigned, the Tray Icon may not be shown. This might be a reason do decide to use the TrayIcon with only a menu and not depend on a calling a click handler.
* Falls back to Old SystemTray if LibAppIndicator3 fails.
 
  
'''Its Gnome isn't it ?'''
+
Tests have been conducted on a wide range of commonly used distributions and desktop combinations prior to release of Lazarus 2.0.6. Using Lazarus versions prior to that will produce different results and changes to how future Linux distribution work with the System Tray is to be expected.
 
 
Yes, frankly, this problem seems to be driven by Gnome, particularly in RedHat where they are quite close to the Gnome Team. Ubuntu seems committed to minimizing its impact at present and the non Gnome Mageia products seem OK. Linux Mint has indicated it will drop SystemTray in 19.3 (Confirm that Davo). Much more testing is needed on non-Gnome distros.
 
  
 
=== References ===
 
=== References ===
Line 38: Line 23:
 
* https://bugs.freepascal.org/view.php?id=35983 - reprot that lead to reverting back to Old System Tray Mode
 
* https://bugs.freepascal.org/view.php?id=35983 - reprot that lead to reverting back to Old System Tray Mode
 
* https://forum.lazarus.freepascal.org/index.php/topic,46912.msg335018.html#msg335018 - forum discussion.
 
* https://forum.lazarus.freepascal.org/index.php/topic,46912.msg335018.html#msg335018 - forum discussion.
 
=== Choosing the System Tray Model ===
 
Right now, and this is very temproary, using a Fixes_2_0 version of Lazarus, selecting the release version to be 61820 or earlier will get you a TrayIcon that prefers LibAppIndicator3, falling back to OldSystemTray if libappindicator3 is unavailable. Using one 61821 or later will use only the OldSystemTray model and will fail completely if that is not working.
 
Juha is working on a better approach as I write ....
 
 
=== Raw Data ===
 
 
Below is raw data collected early October, 2019. The test programme is posted on the Forum Page (link to new version of test app).  Many many more distributions need to be tested before this list is even vaguely complete and, obviously, will need updating as new releases are made available. In this section, '820' means using Lazarus Fixes_2_0 release 81620 or earlier. '821' means 61821 or later up to a (soon) future release that tidies up this issue. Confused ?
 
 
'''Mageia 7.1'''
 
* Plasma, 820 {No Menu} SeeIcon=No, {Menu Assigned} SeeIcon=Yes,  LeftClick=Menu, RightClick=Menu
 
* Plasma, 821 {No Menu} SeeIcon=Yes , LeftClick=Click , {Menu Assigned} SeeIcon=Yes,  LeftClick=Click, RightClick=Menu
 
 
* Gnome, 820 {No Menu} SeeIcon=No, {Menu Assigned} SeeIcon=Yes,  LeftClick=Menu
 
* Gnome, 821 {No Menu} SeeIcon=Yes, LeftClick=Click , {Menu Assigned} SeeIcon=Yes,  LeftClick=Click, RightClick=Menu in wrong location
 
 
* Cinnamon, 820 {No Menu} SeeIcon=No, {Menu Assigned} SeeIcon=Yes,  LeftClick=Menu, RightClick=Menu
 
* Cinnamon, 821 {No Menu} SeeIcon=Yes , LeftClick=Click, {Menu Assigned} SeeIcon=Yes,  LeftClick=click, RightClick=Menu
 
 
''Summary - Plasma, Cinnamon and Gnome seems to represent most Mageia users, Plasma and Cinnamon support both Lazarus TrayIcon modes, the Gnome Desktop does not allow the Old System Tray one but does allow the Menu only libappindicator3 mode. I have not yet tried TopIcons with Gnome, Gnome does not seem to be big in the Mageia world.''
 
 
'''Fedora 30'''
 
 
No version of (Gnome) Fedora 30 displays any Lazarus TrayIcon without TopIcons installed and turned on. Even with XOrg selected as Display Manager instead of Wayland this is the case. All tests in this block used TopIconsPlus.
 
 
* Gnome, 820 {No Menu} SeeIcon=No, {Menu Assigned} SeeIcon=Yes,  LeftClick=Menu
 
* Gnome, 821 {No Menu} SeeIcon=Yes, LeftClick=Click , {Menu Assigned} SeeIcon=Yes,  LeftClick=Click, RightClick=Menu in wrong location
 
 
Using Gnome on XOrg, With TopIcons
 
* Gnome, 820 {No Menu} SeeIcon=No, {Menu Assigned} SeeIcon=Yes,  LeftClick=Menu
 
* Gnome, 821 {No Menu} SeeIcon=Yes, LeftClick=Click, {Menu Assigned} SeeIcon=No,  LeftClick=Click, RightClick=Menu
 
 
''Summary - no combination without TopIcons will work. With TopIcons, 820 and an assigned menu, that menu can be used.  With TopIcons, replacing Wayland with XOrg and 821 you get a leftclick handler.  Gnome is Fedora's main Desktop, need to test KDE/Plasma at least.''
 
 
--------------------------------
 
'''Ubuntu'''
 
* 19.04 Gnome, 820 {No Menu} SeeIcon=No, {Menu Assigned} SeeIcon=Yes,  LeftClick=Menu, RightClick=Menu
 
* 19.04 Gnome, 821 {No Menu} SeeIcon=No, {Menu Assigned} SeeIcon=No
 
 
* 18.04 Gnome, 820 {No Menu} SeeIcon=No, {Menu Assigned} SeeIcon=Yes,  LeftClick=Menu, RightClick=Menu
 
* 18.04 Gnome, 821 {No Menu} SeeIcon=Yes, LeftClick=Click, {Menu Assigned} SeeIcon=Yes,  LeftClick=Click, RightClick=Menu
 
 
* 18.04 Mate, 820 {No Menu} SeeIcon=No, {Menu Assigned} SeeIcon=Yes,  LeftClick=Menu, RightClick=PanelMenu
 
* 18.04 Mate, 821 {No Menu} SeeIcon=Yes, LeftClick=Click, {Menu Assigned} SeeIcon=Yes,  LeftClick=Click, RightClick=Menu
 
 
(TopIconsPlus Installed)
 
* 19.04 Gnome, 820 {No Menu} SeeIcon=No, {Menu Assigned} SeeIcon=Yes,  LeftClick=Menu, RightClick=Menu
 
* 19.04 Gnome, 821 {No Menu} SeeIcon=Yes, LeftClick=Yes, {Menu Assigned} SeeIcon=Yes,  LeftClick=Click, RightClick=Menu
 
 
''Summary, if you plan to assign a menu and don't want a separate leftclick handler, easy, use the 820 model. If you do need a LeftClick Handler the LTS release, 18.04 is usable for another year but TopIcons and 821 is needed for 19.04 (and presumably 19.10).
 
''
 
 
=== Old Date, remove ? ===
 
In conjunction with bugs 0035723 and 35983 here is a table of what works with (Fixes) release 61820 and 61821 -
 
 
{|  class="wikitable"
 
!Distro
 
!See Icon
 
!LeftClick
 
!RightClick
 
!See Icon with no menu
 
!LeftClick with no menu
 
|-
 
|18.04 Mate 61820
 
|Yes
 
|Menu
 
|Panel Menu
 
|No
 
|
 
|-
 
|18.04 Mate 61821
 
|Yes
 
|Click
 
|
 
|Yes
 
|Click
 
|-   
 
|18.04 Gnome3  61820
 
|Yes
 
|Menu
 
|Menu
 
|
 
|
 
|- style="font-style: italic; color: red;"
 
|18.04 Gnome3  61821
 
|No
 
|,
 
|,
 
|
 
|
 
|-
 
|19.04 Gnome3 61820
 
|Yes
 
|Menu
 
|Menu
 
|
 
|
 
|-  style="font-style: italic; color: red;"
 
|19.04 Gnome3 61821
 
|No
 
|,
 
|,
 
|
 
|
 
|-
 
|Fedora 30  61820
 
|Yes
 
|Menu
 
|Menu
 
|
 
|
 
|-  style="font-style: italic; color: red;"
 
|Fedora 30  61821
 
|Yes
 
|Click
 
|Menu but in random location.
 
|
 
|
 
|-
 
|OpenSuse Leap 61820
 
|Yes
 
|Menu
 
|Menu
 
|
 
|
 
|-  style="font-style: italic; color: red;"
 
|OpenSuse Leap 61821
 
|Yes
 
|Click
 
|Menu but in random location.
 
|
 
|
 
|-
 
|Debian 9.9 (all)
 
|Yes
 
|Click
 
|Menu
 
|
 
|
 
|-
 
| Mint 19.2 Cinnamon 61820
 
| Yes
 
| Menu
 
| Menu
 
|
 
|
 
|-
 
|Mint 19.2 Cinnamon 61821
 
| Yes
 
| Click
 
| Menu
 
|
 
|
 
|-  style="font-style: italic; color: red;"
 
|Mageia 7.1 Gnome 61820
 
|Yes
 
|Menu
 
|Menu
 
|
 
|
 
|- style="font-style: italic; color: red;"
 
|Mageia 7.1 Gnome 61821
 
| No
 
|
 
|
 
|
 
|
 
|-
 
|}
 
 
Fedora 30 and OpenSuse Leap 15 has TopIcons installed, without it no TrayIcon shows in any model. Both confirm tightly Gnome's "No SystemTray Please".
 
 
Debian - Thats Plasma and Gnome3, both versions of test app.
 
 
Mageia may work if TopIcons is installed but I had problems doing so and its almost certain it, too, would suffer the random menu placement issue because it uses Wayland. Mageia may have any number of other Desktops installed, I'll try and find out which are the more popular (my network allowance is taking a bit of a hiding at present).
 
 
Note that the current, mainstream, Fedora and Ubuntu mixes are unusable in 61821 and later. The only downside of the 61820 and earlier is that libappindicator3 does not differentiate between left and right click. Given that the push at present is to "simplify" the SystemTray/AppNotifier model, perhaps thats intentional. Gnome's hostility to the older SystemTray model is well know, and, perhaps sadly, likely to prevail. And that means more systems will be unusable using the old SystemTray/Libappindicator (1) model.
 
  
 
== Legacy ==
 
== Legacy ==
Line 312: Line 120:
  
 
: Now about setting an icon pixel, there is a much better way of doing this. The RawImage is completely dependent on the pixel format you are using, but you can also use TLazIntfImage, which is format independent and very fast:
 
: Now about setting an icon pixel, there is a much better way of doing this. The RawImage is completely dependent on the pixel format you are using, but you can also use TLazIntfImage, which is format independent and very fast:
: <syntaxhighlight>
+
: <syntaxhighlight lang=pascal>
 
  uses Graphics, IntfGraphics;
 
  uses Graphics, IntfGraphics;
  

Latest revision as of 07:23, 17 February 2020


Linux Problems

DRAFT prior to release of Lazarus 2.0.6

Background

Recently, changes in some Linux Desktops that use Gnome have threatened the TrayIcon Lazarus Component. Apparently driven by concern that the Linux System Tray (of which the TrayIcon is an example) is being used in overly complicated User Interfaces and is too hard to maintain at the Desktop level. Some major players have disabled the System Tray altogether, some have replaced it with a simpler model and some still support it.

Most, if not all distributions that don't use Gnome Shell are not a problem. The Gnome Shell desktops, to be used with Lazarus's TrayIcon all require the Gnome Extension, TopIconsPlus or one of its peers be installed. This introduces some issues -

  • End users are uncomfortable installing these Extensions but its unavoidable if they are using a Gnome distribution.
  • libappindicator3 is used (and may also need be installed) and that provides a limited version of the System Tray, a left click is not passed through to TrayIcon1Click(), it can only be used to invoke a PopupMenu. Further, if a menu is not assigned, the Tray Icon may not be shown. This might be a reason do decide to use the TrayIcon with only a menu and not depend on a calling a click handler.

Tests have been conducted on a wide range of commonly used distributions and desktop combinations prior to release of Lazarus 2.0.6. Using Lazarus versions prior to that will produce different results and changes to how future Linux distribution work with the System Tray is to be expected.

References

Legacy

Could someone expand on this comment "The image of the icon can be altered using a HICON handle. "? As a newbie I don't really know what a HICON handle is or how to use it.

HICON is a widgetset Icon Handle. The TrayIcon component is quite old, and when I first wrote it there was no real support for the TIcon component is Lazarus, so you could use directly an icon handle instead. Now you should just go for TIcon.
--Felipe Monteiro de Carvalho 08:41, 25 July 2010 (CEST)

I have found it quite hard to generate icons that will load and display using

SysTrayIcon.LoadFromFile('file.ico');
SysTrayIcon.Show;
Should work.
--Felipe Monteiro de Carvalho 08:41, 25 July 2010 (CEST)

I found that the format of the icon in Windows XP is fussy. The icon will only display if it is saved with the parameters "8bpp,1-bit alpha,256-slot palette" in gimp for example.

Ummm ... that's probably something related to the Free Pascal Windows Icon reading capabilities. 24-bits RGB should work too. Doesn't it work? You can create a test project and attach it to a bug report in the bug tracker. It would also be great if you could find out which formats work and which don't and write this in the wiki.
--Felipe Monteiro de Carvalho 08:41, 25 July 2010 (CEST)

The next challenge is to modify an icon in memory and then display it. I'm sure my method isn't exactly correct but maybe it will help others. First I tried to create a tbitmap and load an icon into it but fails. Also any attempt to do a SysTrayIcon.Icon.LoadFromBitMapHandles() seems to result in a blank icon.

In the end I did this which works for a 32x32 icon

MemIcon:=TIcon.Create;
MemIcon.LoadFromLazarusResource('blankicon');
PByte:=MemIcon.RawImage.Data+100;
//PByte now points to the first byte of the first pixel.
//Set the top left pixel red
Pbyte^:=$00; //green
(PByte+1)^:=$FF;  //red
(PByte+2)^:=$00:  //blue
SysTrayIcon.Icon:=MemIcon;
SysTrayIcon.Show:

Now I have an icon in my system tray with a red dot in the top left corner. Each pixel uses 3 bytes so a procedure like this works to manipulate each 32x32 pixel

procedure TForm1.SetIconPixel(PTRIcon:PIcon;xpos,ypos,red,green,blue:byte);
var
  PByte: ^Byte;
begin
  {xpos and ypos are 0 to 31}
  PByte:=PtrIcon^.RawImage.Data+100+((xpos+(ypos*32))*3);
  if PByte<PtrIcon^.RawImage.Data+PtrIcon^.RawImage.DataSize-1 then
  begin
    Pbyte^:=green;
    (PByte+1)^:=red;
    (PByte+2)^:=blue;
  end;
end;

I have no idea what the first 100 bytes do.

For a 16x16 icon there is no extra 100 bytes and the colour order is different. Same code for a 16x16 icon

procedure TForm1.SetIconPixel(PTRIcon:PIcon;xpos,ypos,red,green,blue:byte);
var
  PByte: ^Byte;
begin
  {xpos and ypos are 0 to 15}
  PByte:=PtrIcon^.RawImage.Data+((xpos+(ypos*16))*3);
  if PByte<PtrIcon^.RawImage.Data+PtrIcon^.RawImage.DataSize-1 then
  begin
    Pbyte^:=blue;
    (PByte+1)^:=green;
    (PByte+2)^:=red;
  end;
end;

To use this procedure you have to load an icon file or resource into a ticon send a pointer to the ticon and the xpos, ypos and colour that you want to the procedure copy the icon to the systrayicon show it

like this

MemIcon:=TIcon.Create;
MemIcon.LoadFromFile('16x16.ico');
//draw a black square in the middle
for x:=6 to 9 do
  for y:=6 to 9 do
    SetIconPixel(@MemIcon,x,y,0,0,0);
SystrayIcon.Icon:=MemIcon;
SystrayIcon.Show;

dieselnutjob

Now about setting an icon pixel, there is a much better way of doing this. The RawImage is completely dependent on the pixel format you are using, but you can also use TLazIntfImage, which is format independent and very fast:
 uses Graphics, IntfGraphics;

 var
   TempIntfImg: TLazIntfImage;
   ImgHandle,ImgMaskHandle: HBitmap;
   px, py: Integer;
   TempBitmap: TBitmap;
 begin
   TempIntfImg:=TLazIntfImage.Create(16,16);
   TempBitmap:=TBitmap.Create;

   // Here you can set the pixels
   for py:=0 to TempIntfImg.Height-1 do
     for px:=0 to TempIntfImg.Width-1 do
       SrcIntfImg.Colors[px,py] := clRed;

   // Now you can copy it to a TBitmap
   TempIntfImg.CreateBitmaps(ImgHandle,ImgMaskHandle,false);
   TempBitmap.Handle:=ImgHandle;
   TempBitmap.MaskHandle:=ImgMaskHandle;

   // And copy the TBitmap to your Icon
   SystrayIcon.Icon.Assign(TempBitmap);

   TempIntfImg.Free;
   TempBitmap.Free;
 end;
That should do it and very 100% format independent.
--Felipe Monteiro de Carvalho 08:40, 25 July 2010 (CEST)

I can't get TempIntfImg.CreateBitmaps(ImgHandle,ImgMaskHandle,false) to actually run getting FPImageException: Failed to create handles bug 0017031 created dieselnutjob

For reference, I added a working code here: TrayIcon#Example_2_-_Creating_the_icon_with_TLazIntfImage
--Felipe Monteiro de Carvalho 17:38, 26 July 2010 (CEST)

Your code works well. I tried it in Linux and Windows XP. just removed the unnecessary "FPRed: TFPColor;" variable thanks dieselnutjob

I am getting a new problem now. With the example code on Linux the red box is scrambled. for an example see http://christiantena.pwp.blueyonder.co.uk/images/redbox.jpg This is laptop running Debian Lenny with KDE desktop. Lazarus is 0.9.28.2-0 beta Date 2009-10-27 FPC 2.2.4 thanks dieselnutjob