Recent

Author Topic: [SOLVED] How to hide a Form but display a TPopupNotifier? (LCL problem on Linux)  (Read 3066 times)

Hartmut

  • Hero Member
  • *****
  • Posts: 1153
As so often FPC and LCL work easily on Windows, but on Linux I have endless pain. Again I need your help.

I want to write a little program which shows a PopupNotifier for some seconds, but I don't want to see the Form of the program meanwhile. It should completely hide. I reduced it to a small demo:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, PopupNotifier, StdCtrls;
  9.  
  10. type
  11.  
  12.  { TForm1 }
  13.  
  14.  TForm1 = class(TForm)
  15.   Button1: TButton;
  16.   procedure Button1Click(Sender: TObject);
  17.  private
  18.  public
  19.  end;
  20.  
  21. var Form1: TForm1;
  22.  
  23. implementation
  24.  
  25. {$R *.lfm}
  26.  
  27. var PN1: TPopupNotifier;
  28.  
  29. procedure popNotifyOn(x0,y0, xb,yh: integer; title,msg: ansistring);
  30.    {displays a PopupNotifier until popNotifyOff() is called}
  31.    begin
  32.    PN1:=TPopupNotifier.Create(nil);
  33.    PN1.Title:=title;
  34.    PN1.Text:=msg;
  35.    PN1.Color:=TColor($C0FFFF); {Background-color}
  36.    PN1.vNotifierForm.Width:=xb;
  37.    PN1.vNotifierForm.Height:=yh;
  38.  
  39. writeln('ShowAtPos: ', x0, ' / ', y0);
  40.    PN1.ShowAtPos(x0,y0);
  41.    Application.ProcessMessages;
  42.    sleep(2000); // this line is only for testing purposes to demonstrate
  43.    end;         // that the PopupNotifier is definitely visible
  44.  
  45. procedure popNotifyOff;
  46.    {hides the PopupNotifier which was enabled by popNotifyOn()}
  47.    begin
  48.    PN1.Hide;
  49.    PN1.Free;
  50.    end;
  51.  
  52. { TForm1 }
  53.  
  54. procedure TForm1.Button1Click(Sender: TObject);
  55.    var n: integer;
  56.    begin
  57.    self.Hide;
  58.    Application.ProcessMessages;
  59. // sleep(1500);
  60.  
  61.    popNotifyOn(300,800,300,100, 'Title', 'This is a message');
  62.    writeln('Start Loop...'); // deleting this line doesn't help
  63.  
  64.    for n:=1 to 40 do {wait 4 seconds: }
  65.       begin
  66.       Application.ProcessMessages;
  67.       sleep(100);
  68.       end;
  69.    writeln('Hide PopupNotifier now');
  70.    popNotifyOff;
  71.    Close;
  72.    end;
  73.  
  74. end.

On Windows everything works perfectly: the Form is hidden (line 57) and the PopupNotifier is displayed (line 40), until popNotifyOff() is called (line 70).

But on Linux the PopupNotifier is visible only for 2 seconds (line 42). As soon as "Start Loop..." is displayed (line 62), the PopupNotifier disappears! So during the following loop (4 seconds) I don't see the PopupNotifier...

What I don't understand: in line 41 Application.ProcessMessages() and sleep() dont't disturb, but in line 66 exactly the same commands hide the PopupNotifier.

I'm on Linux Ubuntu 18.04 and tried with Lazarus 2.0.10 and 2.0.6 and 1.8.4 with all the same result.
What do I do wrong? I attached a compilable demo. Thanks in advance.
« Last Edit: February 21, 2022, 07:07:13 pm by Hartmut »

Handoko

  • Hero Member
  • *****
  • Posts: 5557
  • My goal: build my own game engine using Lazarus
Re: How to hide a Form, but display a TPopupNotifier? (LCL problem on Linux)
« Reply #1 on: February 21, 2022, 12:45:19 pm »
Tested on Lazarus 2.2.0 64-bit GTK2 Ubuntu Mate 21.10, and this is what I found:
If the system detects that the application has no visible form, the TPopupNotifier will be automatically closed.

I don't say there is no workaround, you may able to 'hack' into the GTK and change the behavior but it may or may not work on other GTK versions. So I think the best you can do is, write a custom form and use it as a popup notifier. How making a form to show but hide the previous one, you can try to search how to do splash form, that should give you the idea.

Hartmut

  • Hero Member
  • *****
  • Posts: 1153
Re: How to hide a Form, but display a TPopupNotifier? (LCL problem on Linux)
« Reply #2 on: February 21, 2022, 03:58:15 pm »
Hello Handoko, thank you for helping me again.

So I think the best you can do is, write a custom form and use it as a popup notifier. How making a form to show but hide the previous one, you can try to search how to do splash form, that should give you the idea.

This would be far beyond my capabilities...

Quote
Tested on Lazarus 2.2.0 64-bit GTK2 Ubuntu Mate 21.10, and this is what I found:
If the system detects that the application has no visible form, the TPopupNotifier will be automatically closed.

Do I understand you right, that GTK3 or QT might work? I'm a bloody beginner to that stuff...

I tried to compile my program with GTK3 and got:
/usr/bin/ld: -lgtk-3 cannot be found
/usr/bin/ld: -lgdk-3 cannot be found
project1.lpr(27,1) Error: Error while linking


I tried to compile my program with qt and got:
linker: /usr/bin/ld: -lQt4Pas cannot be found

I tried to compile my program with qt5 and got:
linker: /usr/bin/ld: -lQt5Pas cannot be found

Does this mean, that I must only install 1 or 2 libraries and then I could compile and run my demo on my Ubuntu 18.04 64-bit with KDE Plasma desktop using GTK3 or QT? Without damaging my system that way?

If yes, I would like to try it, but in Packet Managers Synapse/Muon I did not find libraries with exactly the mentioned names, but dozens of similar names. Could someone please tell me the correct library names which I had to install? Thanks.

Zvoni

  • Hero Member
  • *****
  • Posts: 3433
Re: How to hide a Form, but display a TPopupNotifier? (LCL problem on Linux)
« Reply #3 on: February 21, 2022, 04:04:19 pm »
search for libqt5pas and libqt5pas-dev
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

AlexTP

  • Hero Member
  • *****
  • Posts: 2725
    • UVviewsoft

Hartmut

  • Hero Member
  • *****
  • Posts: 1153
Re: How to hide a Form, but display a TPopupNotifier? (LCL problem on Linux)
« Reply #5 on: February 21, 2022, 05:48:10 pm »
Thanks Zvoni for that info. I could install both libraries, but now I get another linker error:

Code: Text  [Select][+][-]
  1. Free Pascal Compiler version 3.2.0-r45643 [2020/12/20] for x86_64
  2. Copyright (c) 1993-2020 by Florian Klaempfl and others
  3. (1002) Target OS: Linux for x86-64
  4. (3104) Compiling project1.lpr
  5. (3104) Compiling unit1.pas
  6.  
  7. (9015) Linking /hg/utis/project1
  8. /opt/lazarus_210/lazarus/lcl/units/x86_64-linux/qt5/qtwidgets.o: in function »SETTEXTHINT«:
  9. /opt/lazarus_210/lazarus/lcl/interfaces//qt5/qtwidgets.pas:10167: Warning: undefined Link to »QTextEdit_setPlaceholderText«
  10. /media/H/Progs/Lazarus/work/Experimente/Forum17_BalloonTip/project1.lpr(27,1) Error: (9013) Error while linking
  11. /media/H/Progs/Lazarus/work/Experimente/Forum17_BalloonTip/project1.lpr(27,1) Fatal: (10026) There were 1 errors compiling module, stopping
  12. Fatal: (1018) Compilation aborted
  13. Error: /opt/lazarus_210/fpc/bin/x86_64-linux/ppcx64 returned an error exitcode
  14.  

I get this linker error with Lazarus 2.0.10 and 2.0.6. With Lazarus 1.8.4 I get no linker error, but the program crashes immediately when started:

[FORMS.PP] ExceptionOccurred
  Sender=EAccessViolation
  Exception=Access violation
  Stack trace:
  $0000000000435908
  $00000000006D9B17
  $00000000006CD65E
...

Quote
>search for libqt5pas

https://wiki.freepascal.org/CudaText#Linux_Qt5_build

Thanks Alextp, I installed ver 2.6-4

Can anybody help to get the small demo running with qt5?
Or does someone know the neccessary libraries (see reply #2) for GTK3 and qt4?
« Last Edit: February 21, 2022, 05:52:18 pm by Hartmut »

Handoko

  • Hero Member
  • *****
  • Posts: 5557
  • My goal: build my own game engine using Lazarus
Re: How to hide a Form, but display a TPopupNotifier? (LCL problem on Linux)
« Reply #6 on: February 21, 2022, 06:16:56 pm »
So I think the best you can do is, write a custom form and use it as a popup notifier. How making a form to show but hide the previous one, you can try to search how to do splash form, that should give you the idea.

This would be far beyond my capabilities...

I quickly written a demo, it should give you the idea how to write yourself a custom popup. It is tested on Ubuntu Mate GTK2, the font, size and position may need to readjust if you want to run it on other platforms.

Code: Pascal  [Select][+][-]
  1. unit frmCustomPopup;
  2.  
  3. {$mode ObjFPC}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls;
  9.  
  10. type
  11.  
  12.   { TCustomPopup }
  13.  
  14.   TCustomPopup = class(TForm)
  15.     Label1: TLabel;
  16.     Label2: TLabel;
  17.     Timer1: TTimer;
  18.     procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
  19.     procedure FormCreate(Sender: TObject);
  20.     procedure FormShow(Sender: TObject);
  21.     procedure Timer1Timer(Sender: TObject);
  22.   private
  23.     FAutoClose:   Boolean;
  24.     FPosX, FPosY: Integer;
  25.     FCaller:      TForm;
  26.     FCounter:     Integer;
  27.   public
  28.     procedure SetLine(const S: string);
  29.     procedure SetAutoClose(Autoclose: Boolean);
  30.     procedure SetAutoCenter(Autocenter: Boolean);
  31.     procedure SetFormColor(aColor: TColor);
  32.     procedure Show(TheCaller: TForm); overload;
  33.   end;
  34.  
  35. var
  36.   CustomPopup: TCustomPopup;
  37.  
  38. implementation
  39.  
  40. {$R *.lfm}
  41.  
  42. { TCustomPopup }
  43.  
  44. procedure TCustomPopup.FormCreate(Sender: TObject);
  45. begin
  46.   FAutoClose           := False;
  47.   FPosX                := Left;
  48.   FPosY                := Top;
  49.   FCaller              := nil;
  50.   FCounter             := 0;
  51.   Label2.Anchors       := [akLeft] + [akBottom];
  52.   Timer1.Enabled       := False;
  53.   BorderStyle          := bsDialog;
  54.   Constraints.MinWidth := 220;
  55. end;
  56.  
  57. procedure TCustomPopup.FormClose(Sender: TObject; var CloseAction: TCloseAction
  58.   );
  59. begin
  60.   if Assigned(FCaller) then
  61.     FCaller.Visible := True;
  62. end;
  63.  
  64. procedure TCustomPopup.FormShow(Sender: TObject);
  65. begin
  66.   Label2.Visible := FAutoClose;
  67.   case FAutoClose of
  68.     True:
  69.       begin
  70.         Height         := Label1.Height + 65;
  71.         FCounter       := 6;
  72.         Timer1.Enabled := True;
  73.         Timer1Timer(Self);
  74.       end;
  75.     False:
  76.       Height := Label1.Height + 50;
  77.   end;
  78.   Width := Label1.Width + 40;
  79. end;
  80.  
  81. procedure TCustomPopup.Timer1Timer(Sender: TObject);
  82. var
  83.   S: string;
  84. begin
  85.  
  86.   Dec(FCounter);
  87.   if FCounter <= 0 then
  88.     Timer1.Enabled := False;
  89.  
  90.   S := FCounter.ToString + ' second';
  91.   if FCounter > 1 then
  92.     S := S + 's';
  93.   Label2.Caption := 'Will be close in ' + S;
  94.  
  95.   if FAutoClose and (FCounter <= 0) then Close;
  96.  
  97. end;
  98.  
  99. procedure TCustomPopup.SetLine(const S: string);
  100. begin
  101.   Label1.Caption := S;
  102. end;
  103.  
  104. procedure TCustomPopup.SetAutoClose(Autoclose: Boolean);
  105. begin
  106.   FAutoClose := Autoclose;
  107. end;
  108.  
  109. procedure TCustomPopup.SetAutoCenter(Autocenter: Boolean);
  110. begin
  111.   case Autocenter of
  112.     True:
  113.       Position := poDesktopCenter;
  114.     False:
  115.       begin
  116.         Position := poDesigned;
  117.         Left     := FPosX;
  118.         Top      := FPosY;
  119.       end;
  120.   end;
  121. end;
  122.  
  123. procedure TCustomPopup.SetFormColor(aColor: TColor);
  124. begin
  125.   Color := aColor;
  126. end;
  127.  
  128. procedure TCustomPopup.Show(TheCaller: TForm);
  129. begin
  130.   FCaller := TheCaller;
  131.   if Assigned(TheCaller) then
  132.     TheCaller.Visible := False;
  133.   Show;
  134. end;
  135.  
  136. end.
« Last Edit: February 21, 2022, 06:18:33 pm by Handoko »

Hartmut

  • Hero Member
  • *****
  • Posts: 1153
Re: How to hide a Form, but display a TPopupNotifier? (LCL problem on Linux)
« Reply #7 on: February 21, 2022, 07:06:38 pm »
Thank you very, very much Handoko for that great Unit and for your demo!
It works perfectly on my system, even if the main Form is hidden. That is exactly what I was for.
I'm optimistic now, that my capabilities are enough to make some minor changes for my needs.
This is a great Forum!

 

TinyPortal © 2005-2018