I don't understand what you expect to happen and in what order. The thing is you show a Modal From before having the application running and that seems, in Windows, to already activate the windows message queue.
Maybe this is the reason, why the clipboard works on Windows and not on Linux.
I tried the following modification to the project code, see if it is nearer to what you expect.
program project1;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
{$IFDEF HASAMIGA}
athreads,
{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms,
unit1,
Unit2 { you can add units after this };
{$R *.res}
begin
// with the following code block it works only on Windows, but NOT on Linux:
RequireDerivedFormResource := True;
Application.Scaled := True;
Application.Initialize;
writeln('AAA');
writeln('BBB');
Form1 := TForm1.Create(Application); // Create Form1.Instance
Form1.FormActivate(Application); // Call Form2.ShowModal before activating Form1
if not Application.Terminated then begin
Form1.Show;
writeln('Call Application.Run');
Application.Run;
end
else
Application.Free;
end.
Thanks for your suggestion, I tried it. Now the clipboard works on Linux, but Application.Run() is started again too late: The whole "main task" is done in Unit2.Test_Clipboard(), which is called from inside 'Form1.FormActivate(Application)', which will only return, *after' the "main task" had been finished by the "X" in the upper right corner of Form2. The issue with Application.Run() is, that Application.Run() is only started, *after* you exited Form2. But then the "main task" had already finished. So the "main task" could not benefit from the loop in Application.Run().
I hesitate to rely on this solution, because the "main task" runs completely without the loop from Application.Run() and I fear for unpredictable side affects running a GUI program without Application.Run().
Setting Form1.Visible to False does not work in FormCreate(). It only works in FormActivate(). And this produces a short flicker, which I wanted to avoid by using 'Application.ShowMainForm:=false'.
Try to set it invisible into the Designer. Not in FormCreate().
I had tried this already before, but unfortunately it does not work. Would have been the easiest solution...
I remembered today of a colleague years ago using {$APPTYPE CONSOLE} in Delphi to hide the main form. Visible still needs to be false and you can to away with Application.ShowMainForm in the .lpr. Maybe this will help??
The purpose of {$APPTYPE CONSOLE} is to enable a console output on Windows. On Linux it instead invokes a compiler warning "Warning: APPTYPE is not supported by the target OS".
Diving into Application.CreateForm reveals that the modal form is shown very very early before anything has had a chance to setup properly. Basically this is because Form2 is created and shown in the OnCreate handler. Buth rather than doing this immediately in this event handler you should delay its execution. A convenient way to do this is calling the QueueAsyncCall method of the Application - it just puts the request to create and show into the message queue and lets the program continue until the Run method entered and the message queue command are handled. Now everything works correctly (in my opinion).
Thanks a lot wp for this suggestion. The good news is: Application.Run() is now started early enough. The bad news is: the clipboard on Linux does however not work. Instead it writes the same error message on the console as before. This is the complete console output:
AAA
FormCreate
BBB
CCC
ShowForm2
(project1:10240): Gtk-CRITICAL **: 12:28:05.193: IA__gtk_selection_owner_set: assertion 'widget == NULL || gtk_widget_get_realized (widget)' failed
DDD
This is the new main unit:
unit Unit1; {main unit}
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, unit2;
type
{ TForm1 }
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure ShowForm2(Data: PtrInt);
private
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
writeln('FormCreate');
Application.QueueAsyncCall(@ShowForm2, 0);
end;
procedure TForm1.ShowForm2(Data: PtrInt); // This is the signature needed by QueueAsyncCall
begin
writeln('ShowForm2');
Unit2.Test_Clipboard; {saves a graphic file into the clipboard}
Application.Terminate;
end;
end.
I attached the updated project (including an updated project file) for you.
Can it be that there is a
bug in the gtk2 clipboard or it's initialization ???
Versions: Linux Ubuntu 22.04 64-bit with Lazarus 3.4.0 gtk2.