Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2011-04

Message Loop paused when no interaction with mouse?

62 messages · 9 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Bernd

Hi,

I am sure I have read some discussion about this already but I cannot find it anymore, so I will ask here, I don't know whether it is a bug or intentional and I am only using it wrongly. The following is what I have and what I am trying to do:

* Linux (KDE3.5, windowmanager is kwin) Lazarus is latest SVN, LCL widgetset is GTK+
* a TForm with a TImage
* a TThread (started when the form is created, running forever, automatically drawing to the TImage)

The GUI thread is idle, the form is responsive, all the work is done in the separate TThread. This thread will wait for RGB data from a camera on a named pipe and read it and then write pixels in the TImage via Image.Picture.Bitmap.RawImage.Data[somewhere]^ . It will call Image.Picture.Bitmap.BeginUpdate before it starts and EndUpdate after it is done and this is all working fine.

Exactly after each frame i can see there is the OnPictureChanged event triggered, I can verify this with:

procedure TForm1.DisplayPictureChanged(Sender: TObject);
begin
  writeln('\n*** frame ***');
end;

It will print '*** frame ***'' three times a second, exactly the frame rate of my camera. If I move the mouse around on the form I can see my TImage updating at the same rate. I just have to move the mouse. As soon as I stop moving the mouse over the form the TImage will not update anymore. The events will still be fired, I can still see it printing *** frame *** nicely every 300ms to the console, only the TImage won't update.

I tried to call the Repaint method of the TImage (from within its OnPictureChanged handler) but this will freeze it (infinite loop?), I tried Image.Invalidate, I tried the same with the entire form, I tried calling Application.HandleMessage (giving me GTK warnings about the wrong thread (?) in the console), some things froze it, some crash it and some have no have also tried several things with Synchonize() and somehow managed to freeze it but since I now already have my TImage firing its event I figured out this would be the right place from where I should try to update the GUI. But I can't find it.

Is this a bug or am I just missing something? The only way I have found working is if I put a timer onto the form and then only this:

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  //
end;

This empty event method is already enough to wake up the form and "simulate" what I did with my mouse move. But I don't want to have a timer firing every few milliseconds (it has to be really fast because I can set my camera to much shorter exposure and higher frame rate), this simply does not "look right" to me, I would rather have it call the right method exactly after a new frame has arrived.

Since I cannot find anything with google relating to this I have written this rather lengthy essay, hoping all possible search terms are now included and the next one with this problem will find this thread.

Reply by email

Henry Vermaak
to Bernd
Bernd wrote 67 lines
Hi, I am sure I have read some discussion about this already but I cannot find it anymore, so I will ask here, I don't know whether it is a bug or intentional and I am only using it wrongly. The following is what I have and what I am trying to do: * Linux (KDE3.5, windowmanager is kwin) Lazarus is latest SVN, LCL widgetset is GTK+ * a TForm with a TImage * a TThread (started when the form is created, running forever, automatically drawing to the TImage) The GUI thread is idle, the form is responsive, all the work is done in the separate TThread. This thread will wait for RGB data from a camera on a named pipe and read it and then write pixels in the TImage via Image.Picture.Bitmap.RawImage.Data[somewhere]^ . It will call Image.Picture.Bitmap.BeginUpdate before it starts and EndUpdate after it is done and this is all working fine. Exactly after each frame i can see there is the OnPictureChanged event triggered, I can verify this with: procedure TForm1.DisplayPictureChanged(Sender: TObject); begin writeln('\n*** frame ***'); end; It will print '*** frame ***'' three times a second, exactly the frame rate of my camera. If I move the mouse around on the form I can see my TImage updating at the same rate. I just have to move the mouse. As soon as I stop moving the mouse over the form the TImage will not update anymore. The events will still be fired, I can still see it printing *** frame *** nicely every 300ms to the console, only the TImage won't update. I tried to call the Repaint method of the TImage (from within its OnPictureChanged handler) but this will freeze it (infinite loop?), I tried Image.Invalidate, I tried the same with the entire form, I tried calling Application.HandleMessage (giving me GTK warnings about the wrong thread (?) in the console), some things froze it, some crash it and some have no effect at all. I have also tried several things with Synchonize() and somehow managed to freeze it but since I now already have my TImage firing its event I figured out this would be the right place from where I should try to update the GUI. But I can't find it. Is this a bug or am I just missing something? The only way I have found working is if I put a timer onto the form and then only this: procedure TForm1.Timer1Timer(Sender: TObject); begin // end; This empty event method is already enough to wake up the form and "simulate" what I did with my mouse move. But I don't want to have a timer firing every few milliseconds (it has to be really fast because I can set my camera to much shorter exposure and higher frame rate), this simply does not "look right" to me, I would rather have it call the right method exactly after a new frame has arrived. Since I cannot find anything with google relating to this I have written this rather lengthy essay, hoping all possible search terms are now included and the next one with this problem will find this thread.

See here for a related issue:

http://bugs.freepascal.org/view.php?id=13120

You'll have to wake up the main thread after the frame (which is what your timer is doing). For gtk you can use
g_main_context_wakeup(g_main_context_default), for qt there is QEventLoop::wakeUp().

Henry

Reply by email

Bernd
to Henry Vermaak: See here for a related issue: http://bugs.freepascal.org/view.php?id=13120 You'll have to…

2011/4/20 Henry Vermaak :

Show quoted text 8 lines
See here for a related issue: http://bugs.freepascal.org/view.php?id=13120 You'll have to wake up the main thread after the frame (which is what your timer is doing). ?For gtk you can use g_main_context_wakeup(g_main_context_default), for qt there is QEventLoop::wakeUp().

Thank you, this is what I have read a while ago but could not find anymore due to the wrong serch terms.

But it does not seem to help :-(

This is how my thread looks like now:

procedure Execute;
begin
  while ...
  begin
    ...
    ...
    if ...
    begin
      ...
      ...
      ppx := PInteger(Display.Picture.Bitmap.RawImage.Data);
      for y:=0 to CAM_HEIGHT-1 do begin
        for x:=0 to CAM_WIDTH-1 do begin
          with CamImage[y,x] do begin
            ppx^ := Red << 16 + Green << 8 + Blue;
            ppx += 1;
          end;
        end;
      end;
      writeln('---------------- QueueAsyncCall()');
      Application.QueueAsyncCall(@FrameComplete, 0);
      g_main_context_wakeup(g_main_context_default);
    end;
  end;
end;
procedure TReceiver.FrameComplete(data: PtrInt);
begin
  writeln('**************** in FrameComplete()');
  Display.Picture.Bitmap.EndUpdate();
  Display.Picture.Bitmap.BeginUpdate();
end;

it will happily print '---------------- QueueAsyncCall()' to the console after every frame but nothing else and only if I move the mouse I will get a whole bunch of meanwhile accumulatd '**************** in FrameComplete()' interleaved with the subsequent writeln from my TImage.OnPictureChanged() event handler all at once until the queue is empty again.

Without mouse still no way to wake up the GUI.

Synchronize() instead of QueueAsyncCall() would halt my thread completely because it would wait for the sleeping GUI and never return until I move the mouse. nd also It is not clear to me how this could ever work with synchronize() at ll since i would have to wake up the GUI *after* the call but then my thread would be blocked already.

I think this is a serious problem. How is Synchonize() supposed to be used at all? It seems it has no use at all with this bug at the moment?

Reply by email

Henry Vermaak
to Bernd
Bernd wrote 15 lines
2011/4/20 Henry Vermaak: > See here for a related issue: > > http://bugs.freepascal.org/view.php?id=13120 > > You'll have to wake up the main thread after the frame (which is what your > timer is doing). For gtk you can use > g_main_context_wakeup(g_main_context_default), for qt there is > QEventLoop::wakeUp(). Thank you, this is what I have read a while ago but could not find anymore due to the wrong serch terms. But it does not seem to help :-(

Hmm, that's strange. This works for me. I've written a c lib that notifies me of usb devices getting plugged in. The callback from the lib looks like this:

procedure NotifyPlug(status: cint); cdecl;
begin
   Application.QueueAsyncCall(@Form1.NotifyAsync, status);
   {$ifdef lclgtk2}
   g_main_context_wakeup(g_main_context_default);
   {$else}
   PostMessage(Form1.Handle, LM_PAINT, 0, 0);
   {$endif}
end;

Does it make a difference if you define usecthreads? Perhaps you can try postmessage, too, just to rule out a bug with the QueueAsyncCall implementation. Postmessage (at least on gtk) will wake up the main thread (make sure you define usecthreads for this, though).

Henry

Reply by email

Michael Schnell
to Bernd: 2011/4/20 Henry Vermaak : Thank you, this is what I have read a while ago but could not…
Bernd wrote
But it does not seem to help :-(

It does not, as it is not fixed.

Running my testing program with the GTK "Widget Type", with the newest svn version, TThread.Synchronize in fact seems to work, but Application.QueuAsyncCall shows the behavior you mentioned. So there still something is wrong in the infrastructure of the event queuing mechanism.

-Michael

Reply by email

Bernd
to Michael Schnell

2011/4/20 Michael Schnell :

Running my testing program with the GTK "Widget Type", with the newest svn version, TThread.Synchronize in fact seems to work

I have now updated to SVN rev. 30401 and the attached demo shows the error. Synchronize does not work. The demo contains nothing but an edit and a thread that will write numbers into the edit field via a call to Synchronize(). As soon as take focus away or even just stop moving the mouse the thread will block in a call to Synchronize().

Are there any other ways under GTK2 (or xorg?) to send a message to a window that simulates user interaction? I need to find some kind of workaround to wake up the GUI.

What exactly does the TTimer do when it fires its event? The TTimer seems to have the power to wake up the GUI, maybe I can do the same manually?

Reply by email

zeljko
to Bernd
Bernd wrote 5 lines
2011/4/20 Bernd : > the attached demo Sorry, forgot to attach it. its less than 2kb, so I think its ok to attach it here

Lazarus 0.9.31 r30393M FPC 2.4.3 i386-linux-qt, but both (qt and gtk2) works fine with this demo (edit.Text is updated frequently without any mouse/kbd interaction).

zeljko

Reply by email

Henry Vermaak
to Bernd: 2011/4/20 Michael Schnell : I have now updated to SVN rev. 30401 and the attached demo…
Bernd wrote
Are there any other ways under GTK2 (or xorg?) to send a message to a window that simulates user interaction? I need to find some kind of workaround to wake up the GUI.

As I've noted before, PostMessage does wake up the main thread (when you compile your project with -dusecthreads). And I use QueueAsyncCall with a manual wakeup, which works well for me on win32 and gtk2. I use svn head, by the way.

Henry

Reply by email

zeljko
to Henry Vermaak
Henry Vermaak wrote 9 lines
On 20/04/11 14:51, Bernd wrote: > Are there any other ways under GTK2 (or xorg?) to send a message to a > window that simulates user interaction? I need to find some kind of > workaround to wake up the GUI. As I've noted before, PostMessage does wake up the main thread (when you compile your project with -dusecthreads). And I use QueueAsyncCall with a manual wakeup, which works well for me on win32 and gtk2. I use svn head, by the way.

I've already answered about that demo in mailing list, but I don't see my answer here, so once again:
Lazarus 30393 gtk,gtk2 and qt works fine. Edit.Text is updated in Worker thread without any interaction of mouse or kbd.

zeljko

Reply by email

Henry Vermaak
to Bernd: 2011/4/20 Michael Schnell : I have now updated to SVN rev. 30401 and the attached demo…
Bernd wrote 10 lines
2011/4/20 Michael Schnell: > Running my testing program with the GTK "Widget Type", with the newest svn > version, TThread.Synchronize in fact seems to work I have now updated to SVN rev. 30401 and the attached demo shows the error. Synchronize does not work. The demo contains nothing but an edit and a thread that will write numbers into the edit field via a call to Synchronize(). As soon as take focus away or even just stop moving the mouse the thread will block in a call to Synchronize().

Your demo works for me on gtk2.

Henry

Reply by email

Michael Schnell
to Bernd: 2011/4/20 Michael Schnell : I have now updated to SVN rev. 30401 and the attached demo…
Bernd wrote
Are there any other ways under GTK2 (or xorg?) to send a message to a window that simulates user interaction?

Something is broken in the infra-structure of the Event queuing mechanism with GTK2 and this can hit in multiple issues. As long as TApplication.QueuAsyncCall() (that supposedly uses the basics of the mechanism) does not work reliably, you can't trust the event scheduling mechanism.

For your own Events you could uses the Windowish "PostMessage" interface to access a "procedure...Message()". Same seems to work with the current GTK2

Last time I checked, TApplication.QueuAsyncCall() did work with the (now unsupported) gtk ("1") Widgest Type.

What exactly does the TTimer do when it fires its event? The TTimer seems to have the power to wake up the GUI, maybe I can do the same manually?

AFAIK the TTimer is just a GUI element direct provided by GTK itself, so the LCL does not need to actively stuff events in the queue and wake the GUI thread.

Stuffing events in the queue seems always to be workable but waking the GUI thread does not seem to work reliably with some Widget Types, so manually waking it by moving the mouse or something like this does make the GUI thread handle all scheduled events. My testing program shows that a TTimer doing nothing indeed wakes the GUI thread and makes it handle the queued events. Also doing a "PostMessage" to an empty "procedure...Message;" seems wake the GUI Thread and makes it handle the queued events.

-Michael

Reply by email

Michael Schnell
to Henry Vermaak: As I've noted before, PostMessage does wake up the main thread (when you compile your…
Henry Vermaak wrote 5 lines
PostMessage does wake up the main thread (when you compile your project with -dusecthreads). And I use QueueAsyncCall with a manual wakeup, which works well for me on win32 and gtk2. I use svn head, by the way.

You are not _supposed_ to do that. QueuAsyncCall _should_ work for itself (instantly and without doing polling ). So this is a work around and not a reliable consideration.

-Michael

Reply by email

Henry Vermaak
to Michael Schnell
Michael Schnell wrote 9 lines
On 04/20/2011 04:05 PM, Henry Vermaak wrote: > PostMessage does wake up the main thread (when you compile your > project with -dusecthreads). And I use QueueAsyncCall with a manual > wakeup, which works well for me on win32 and gtk2. I use svn head, by > the way. > You are not _supposed_ to do that. QueuAsyncCall _should_ work for itself (instantly and without doing polling ). So this is a work around and not a reliable consideration.

Huh, what polling? I know this is not ideal, that's why there is a bug report. All QueueAsyncCall needs to do is to wake up the main thread after it has queued the function. There is nothing "broken in the infrastructure" as you keep saying, or perhaps you'd like to point us to some specific code you find problematic to explain your statements?

Henry

Reply by email

zeljko
to Henry Vermaak
Henry Vermaak wrote 16 lines
On 20/04/11 15:26, Michael Schnell wrote: > On 04/20/2011 04:05 PM, Henry Vermaak wrote: >> PostMessage does wake up the main thread (when you compile your >> project with -dusecthreads). And I use QueueAsyncCall with a manual >> wakeup, which works well for me on win32 and gtk2. I use svn head, by >> the way. > > You are not _supposed_ to do that. QueuAsyncCall _should_ work for > itself (instantly and without doing polling ). So this is a work around > and not a reliable consideration. Huh, what polling? I know this is not ideal, that's why there is a bug report. All QueueAsyncCall needs to do is to wake up the main thread after it has queued the function. There is nothing "broken in the infrastructure" as you keep saying, or perhaps you'd like to point us to some specific code you find problematic to explain your statements?

Have you tried to add WakeUpMainThread in QueueAsyncCall() and test it with all ws ? What happens ?

zeljko

Reply by email

Henry Vermaak
to zeljko
zeljko wrote 21 lines
On Wednesday 20 of April 2011 16:31:59 Henry Vermaak wrote: > On 20/04/11 15:26, Michael Schnell wrote: >> On 04/20/2011 04:05 PM, Henry Vermaak wrote: >>> PostMessage does wake up the main thread (when you compile your >>> project with -dusecthreads). And I use QueueAsyncCall with a manual >>> wakeup, which works well for me on win32 and gtk2. I use svn head, by >>> the way. >> >> You are not _supposed_ to do that. QueuAsyncCall _should_ work for >> itself (instantly and without doing polling ). So this is a work around >> and not a reliable consideration. > > Huh, what polling? I know this is not ideal, that's why there is a bug > report. All QueueAsyncCall needs to do is to wake up the main thread > after it has queued the function. There is nothing "broken in the > infrastructure" as you keep saying, or perhaps you'd like to point us to > some specific code you find problematic to explain your statements? Have you tried to add WakeUpMainThread in QueueAsyncCall() and test it with all ws ? What happens ?

Hehe, we're saying the same thing, but talking past each other. I commented exactly this (with a patch) on the bug tracker, it seems to work for gtk2, can you test with qt?

Henry

Reply by email

Michael Schnell
to Henry Vermaak
Henry Vermaak wrote
Hehe, we're saying the same thing, but talking past each other. I commented exactly this (with a patch) on the bug tracker, it seems to work for gtk2, can you test with qt?

Is this really this simple ?

So hopefully he bug report can be closed soon.

-Michael

Reply by email

Henry Vermaak
to Michael Schnell
Michael Schnell wrote 7 lines
On 04/20/2011 04:50 PM, Henry Vermaak wrote: > > Hehe, we're saying the same thing, but talking past each other. I > commented exactly this (with a patch) on the bug tracker, it seems to > work for gtk2, can you test with qt? Is this really this simple ?

Why not? The workaround is only one line, after all.

Please test your synchronise bug report again, I can't reproduce it.

Henry

Reply by email

Michael Schnell
to Henry Vermaak: Huh, what polling? I know this is not ideal, that's why there is a bug report. All…
Henry Vermaak wrote
There is nothing "broken in the infrastructure" as you keep saying, or perhaps you'd like to point us to some specific code you find problematic to explain your statements?

The fact that the bug report is open since several months and the testing program I provided did not help to fix it suggests that it's a difficult problem embedded deeply in the infrastructure.

-Michael

Reply by email

Bernd
to Henry Vermaak: As I've noted before, PostMessage does wake up the main thread (when you compile your…

2011/4/20 Henry Vermaak :

As I've noted before, PostMessage does wake up the main thread

In which Unit is PostMessage() defined, and also is there some documentation about

procedure ...; message ...;

somewhere, because I can't find anything. Is this an FPC thing (because of the procedure decoration) or is PostMessge() something LCL related and has nothing to do with the message keyword?

Reply by email

Henry Vermaak
to Bernd
Bernd wrote 12 lines
2011/4/20 Henry Vermaak: > As I've noted before, PostMessage does wake up the main thread In which Unit is PostMessage() defined, and also is there some documentation about procedure ...; message ...; somewhere, because I can't find anything. Is this an FPC thing (because of the procedure decoration) or is PostMessge() something LCL related and has nothing to do with the message keyword?

It's a windows thing. More info here:

http://lazarus-dev.blogspot.com/2008/01/new-0926-features-part-1-sendmessage.html

Reply by email

Michael Schnell
to Henry Vermaak: Why not? The workaround is only one line, after all. Please test your synchronise bug…
Henry Vermaak wrote 14 lines
On 20/04/11 16:03, Michael Schnell wrote: > On 04/20/2011 04:50 PM, Henry Vermaak wrote: >> >> Hehe, we're saying the same thing, but talking past each other. I >> commented exactly this (with a patch) on the bug tracker, it seems to >> work for gtk2, can you test with qt? > > Is this really this simple ? Why not? The workaround is only one line, after all. Please test your synchronise bug report again, I can't reproduce it. Henry

Unfortunately LCL does not seem to export WakeUpMainThread() or g_main_context_wakeup(), so I can't test it. :-( .

-Michael

Reply by email

zeljko
to Michael Schnell
Michael Schnell wrote 17 lines
On 04/20/2011 05:04 PM, Henry Vermaak wrote: > On 20/04/11 16:03, Michael Schnell wrote: >> On 04/20/2011 04:50 PM, Henry Vermaak wrote: >>> Hehe, we're saying the same thing, but talking past each other. I >>> commented exactly this (with a patch) on the bug tracker, it seems to >>> work for gtk2, can you test with qt? >> >> Is this really this simple ? > > Why not? The workaround is only one line, after all. > > Please test your synchronise bug report again, I can't reproduce it. > > Henry Unfortunately LCL does not seem to export WakeUpMainThread() or g_main_context_wakeup(), so I can't test it. :-( .

What do you mean by that ? WakeUpMainThread() IS THERE and it works ok, just tested Henry's patch .... gtk,gtk2,qt (linux), win32 (under wine) - example from http://bugs.freepascal.org/view.php?id=13120 works perfect. Now rebuilding laz with that patch to see if something bad can happen with that patch.

zeljko

Reply by email

Henry Vermaak
to Michael Schnell: Unfortunately LCL does not seem to export WakeUpMainThread() or g_main_context_wakeup(),…
Michael Schnell wrote 18 lines
On 04/20/2011 05:04 PM, Henry Vermaak wrote: > On 20/04/11 16:03, Michael Schnell wrote: >> On 04/20/2011 04:50 PM, Henry Vermaak wrote: >>> >>> Hehe, we're saying the same thing, but talking past each other. I >>> commented exactly this (with a patch) on the bug tracker, it seems to >>> work for gtk2, can you test with qt? >> >> Is this really this simple ? > > Why not? The workaround is only one line, after all. > > Please test your synchronise bug report again, I can't reproduce it. > > Henry Unfortunately LCL does not seem to export WakeUpMainThread() or g_main_context_wakeup(), so I can't test it. :-( .

Your synchronise test program works without any patches.

WakeMainThread is in unit classes and g_main_context_wakeup is in glib2.

Henry

Reply by email

Bernd
to Henry Vermaak: It's a windows thing. More info here: http://lazarus-dev.blogspot.com/2008/01/new-0926-fe…

2011/4/20 Henry Vermaak :

This mentions gtk and qt too but unfortunately not where to find it?.

I have found a PostMessage() function defined by lclintf but now I'm still searching for the LM_USER that is mentioned there, also without any reference where it is defined.

__
?) some kind of search index or list of all procedures that are defined in any of the standad units would really be helpful. Each time somebody mentions the name of a procedure or a class that would solve some problem I find myself grepping though the entirety of FPC and LCL sources until I find it.

Reply by email

zeljko
to Henry Vermaak: Your synchronise test program works without any patches. WakeMainThread is in unit…
Henry Vermaak wrote 22 lines
On 20/04/11 16:29, Michael Schnell wrote: > On 04/20/2011 05:04 PM, Henry Vermaak wrote: >> On 20/04/11 16:03, Michael Schnell wrote: >>> On 04/20/2011 04:50 PM, Henry Vermaak wrote: >>>> Hehe, we're saying the same thing, but talking past each other. I >>>> commented exactly this (with a patch) on the bug tracker, it seems to >>>> work for gtk2, can you test with qt? >>> >>> Is this really this simple ? >> >> Why not? The workaround is only one line, after all. >> >> Please test your synchronise bug report again, I can't reproduce it. >> >> Henry > > Unfortunately LCL does not seem to export WakeUpMainThread() or > g_main_context_wakeup(), so I can't test it. :-( . Your synchronise test program works without any patches. WakeMainThread is in unit classes and g_main_context_wakeup is in glib2.

Story is finished. Your patch is applied and issue is marked as resolved :) btw. Thanks for patch.

zeljko

Reply by email

Henry Vermaak
to Bernd: 2011/4/20 Henry Vermaak : This mentions gtk and qt too but unfortunately not where to…
Bernd wrote 11 lines
2011/4/20 Henry Vermaak: > It's a windows thing. More info here: > > http://lazarus-dev.blogspot.com/2008/01/new-0926-features-part-1-sendmessage.html This mentions gtk and qt too but unfortunately not where to find it?. I have found a PostMessage() function defined by lclintf but now I'm still searching for the LM_USER that is mentioned there, also without any reference where it is defined.

LM_USER is in LMessages.

Show quoted text 6 lines
__ ?) some kind of search index or list of all procedures that are defined in any of the standad units would really be helpful. Each time somebody mentions the name of a procedure or a class that would solve some problem I find myself grepping though the entirety of FPC and LCL sources until I find it.

That would be handy, I also do the grep thing, which can be really slow.

Henry

Reply by email

Luca Olivetti
to Bernd: 2011/4/20 Michael Schnell : I have now updated to SVN rev. 30401 and the attached demo…

Al 20/04/2011 15:51, En/na Bernd ha escrit:

What exactly does the TTimer do when it fires its event? The TTimer seems to have the power to wake up the GUI, maybe I can do the same manually?

I don't know, but I've been using for a long time a 10ms timer that just does CheckSynchronize:
under windows when you're dragging a windows it seems that the main loop doesn't fire, so Synchronize calls are blocked, with the timer there's no such problem.

Bye

Luca Olivetti Wetron Automation Technology http://www.wetron.es Tel. +34 935883004 (Ext.133) Fax +34 935883007

Reply by email

Henry Vermaak
to Bernd
Bernd wrote 8 lines
2011/4/20 Henry Vermaak: > As I've noted before, PostMessage does wake up the main thread Confirmed. It does wakeup my GUI, no need for the empty timer anymore. Now I will svn up Lazarus after the latest patch and try my synchronize demo again.

The patch doesn't touch synchronize. It worked o.k. for me before the patch. Maybe it's an fpc issue? I use 2.5.1 (about a month old).

Henry

Reply by email

zeljko
to Luca Olivetti: Al 20/04/2011 15:51, En/na Bernd ha escrit: I don't know, but I've been using for a long…
Luca Olivetti wrote 10 lines
Al 20/04/2011 15:51, En/na Bernd ha escrit: > What exactly does the TTimer do when it fires its event? The TTimer > seems to have the power to wake up the GUI, maybe I can do the same > manually? I don't know, but I've been using for a long time a 10ms timer that just does CheckSynchronize: under windows when you're dragging a windows it seems that the main loop doesn't fire, so Synchronize calls are blocked, with the timer there's no such problem.

Please test with lazarus r30403 if it works without timer. Now, QueueAsyncCall() calls WakeMainThread

Bye

Reply by email

zeljko
to Henry Vermaak: The patch doesn't touch synchronize. It worked o.k. for me before the patch. Maybe it's…
Henry Vermaak wrote 11 lines
On 20/04/11 17:15, Bernd wrote: > 2011/4/20 Henry Vermaak: >> As I've noted before, PostMessage does wake up the main thread > > Confirmed. It does wakeup my GUI, no need for the empty timer anymore. > > Now I will svn up Lazarus after the latest patch and try my > synchronize demo again. The patch doesn't touch synchronize. It worked o.k. for me before the patch. Maybe it's an fpc issue? I use 2.5.1 (about a month old).

I'm using 2.4.3 and Synchronize() works ok.

zeljko

Reply by email

Bernd
to Henry Vermaak: The patch doesn't touch synchronize. It worked o.k. for me before the patch. Maybe it's…

2011/4/20 Henry Vermaak :

The patch doesn't touch synchronize. ?It worked o.k. for me before the patch. ?Maybe it's an fpc issue? ?I use 2.5.1 (about a month old).

I've done some more testing now.

Maybe its my old GTK2 version, I still have Ubuntu Hardy on my laptop and the GTK2 that came with it (don't know which version exactly, I never ever did anything with GTK directly, only through wrappers like wx, etc., so I don't know much about GTK).

I have tried QueueAsyncCall and Synchronize() both don't work here.

PostMessage() works.

PostMessage() is the only one that I have found working without any problems, it has only one little drawback: when I move the mouse over the form it pauses the receiving of messages for about half a second and then continues.

This might be unrelated but at one point while single-stepping through it I have seen a strange loop in gtk2widgetset.inc TGtk2WidgetSet.AppProcessMessages;

where it says:
    // let gtk handle up to 100 messages and call our callbacks
    i:=100;
    while g_main_context_pending(g_main_context_default) and (i>0) do
    begin
      g_main_context_iteration(g_main_context_default, False);
      dec(i);
    end;

and then looped 100 times (not up to 100). This might not be related to the half a second delay but it immediately came to my mind when I noticed the behavior.

Btw: while looking at this code: What is this ifdef USE_GTK_MAIN_OLD_ITERATION which caught my eye, might this be relevant to my problem? Or should I not waste any time with this?

SendMessage()

I was hoping that SendMessage() would be the synchronized counterpart to PostMessage() as I can vaguely remember from my old windows days but it does not seem to be that way in LCL. It behaves like PostMessage() and immediately returns with the only exception that there is again the GUI waking problem, it won't wake up my GUI here without manually interacting wit the mouse.

Conclusion: I will use PostMessge() for now for the purpose of waking up the GUI, for my momentary needs this seems sufficient.

Bernd

Reply by email

zeljko
to Bernd
Bernd wrote
USE_GTK_MAIN_OLD_ITERATION

well, that's old way of using gtk main loop iterations. if you have old gtk2 installation probably you can test with that define (but in that case PostMessage() won't work in multithreaded app).

zeljko

Reply by email

Hans-Peter Diettrich
to Henry Vermaak: LM_USER is in LMessages. That would be handy, I also do the grep thing, which can be…
Show quoted text 7 lines
> ?) some kind of search index or list of all procedures that are > defined in any of the standad units would really be helpful. Each time > somebody mentions the name of a procedure or a class that would solve > some problem I find myself grepping though the entirety of FPC and LCL > sources until I find it. That would be handy, I also do the grep thing, which can be really slow.

View > CodeBrowser

DoDi

Reply by email

Graeme Geldenhuys
to Bernd: 2011/4/20 Henry Vermaak : This mentions gtk and qt too but unfortunately not where to…
Bernd wrote
?) some kind of search index or list of all procedures that are defined in any of the standad units would really be helpful.

You can do this already - at least I can for the last year or so. Generate the fpdoc documentation for RTL, FCL, LCL in fpGUI INF output format. fpdoc output will actually be in xxx.ipf files. Then compile that into binary help using WIPFC (which is included with fpGUI). You can even use skeleton fpdoc output because it will list all procedures, classes, methods etc. Then use fpGUI's DocView help viewer which can concatenate all those help search in DocView is very very fast - under a second to search all those help files. Needless to say, much faster than 'Find in Files' or Grep searching.

If you don't want to go through all that, just wait a few days for me to make the next fpGUI release. Then simply download the pre-built INF docs and binary of DocView. DocView can integrate into Lazarus IDE via the External Tools menu option - so no need to rebuild the IDE, plus you can have offline context sensitive help in Lazarus IDE then too (excluding the IDE help itself, because that is stuck in the online wiki site only).

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/

Reply by email

Graeme Geldenhuys
to Hans-Peter Diettrich: View > CodeBrowser DoDi
Hans-Peter Diettrich wrote
View > CodeBrowser

Nope, that's pretty useless too. See attached screenshot. I tried LM_USER in all the edit fields.

Regards,
- Graeme -

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ -------------- next part -------------- A non-text attachment was scrubbed... Name: Screenshot-Code browser.png Type: image/png Size: 9462 bytes Desc: not available URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20110421/ddd91e13/attachment-0001.png>

Reply by email

Michael Schnell
to Bernd: 2011/4/20 Henry Vermaak : In which Unit is PostMessage() defined, and also is there some…
Bernd wrote
procedure ...; message ...;

In fact even Delphi provides a more appropriate and portable solution for this (when used for having a worker thread send an event to the GUI Thread) : TThread.Queue.

Unfortunately they did not include this in the Delphi Help and this supposedly is the reason why the LCL (in fact the TThread object in the FPC RTL) does not provide it.

-Michael

Reply by email

Michael Schnell
to zeljko: What do you mean by that ? WakeUpMainThread() IS THERE and it works ok, just tested…
zeljko wrote
> Unfortunately LCL does not seem to export WakeUpMainThread() or > g_main_context_wakeup(), so I can't test it. :-( . What do you mean by that ? WakeUpMainThread() IS THERE

I searched the lazarus/trunk and fpc/trunk directories and did not find the text "WakeUpMainThread" in any file. So I took a look at g_main_context_wakeup().

-Michael

Reply by email

Michael Schnell
to Luca Olivetti: Al 20/04/2011 15:51, En/na Bernd ha escrit: I don't know, but I've been using for a long…
Luca Olivetti wrote 5 lines
I don't know, but I've been using for a long time a 10ms timer that just does CheckSynchronize: under windows when you're dragging a windows it seems that the main loop doesn't fire, so Synchronize calls are blocked,

Synchronize supposedly is blocked when there is too much GUI thread activity and the appropriate event does not get handled. Maybe when dragging a window GTK blocks in some event, which is 100% GUI thread activity from the application's point of view.

with the timer there's no such problem.

IMHO, This kind of polling is not a good idea (but just a work around). But of course you can't change what the GTK does when dragging a window :(.

-Michael

Reply by email

Luca Olivetti
to Michael Schnell: Synchronize supposedly is blocked when there is too much GUI thread activity and the…

Al 21/04/2011 10:06, En/na Michael Schnell ha escrit:

Show quoted text 16 lines
On 04/20/2011 06:05 PM, Luca Olivetti wrote: > > I don't know, but I've been using for a long time a 10ms timer that > just does CheckSynchronize: > under windows when you're dragging a windows it seems that the main > loop doesn't fire, so Synchronize calls are blocked, Synchronize supposedly is blocked when there is too much GUI thread activity and the appropriate event does not get handled. Maybe when dragging a window GTK blocks in some event, which is 100% GUI thread activity from the application's point of view. > with the timer there's no such problem. > IMHO, This kind of polling is not a good idea (but just a work around). But of course you can't change what the GTK does when dragging a window :(.

with "under windows" I mean the win32 widgetset, not gtk.

Bye

Luca Olivetti Wetron Automation Technology http://www.wetron.es Tel. +34 935883004 (Ext.133) Fax +34 935883007

Reply by email

Michael Schnell
to Luca Olivetti
Luca Olivetti wrote
with "under windows" I mean the win32 widgetset, not gtk.

Sorry for typing faster than reading once again ;-)

So I suppose the new patch will not help here.

I do not have a Lazarus on Windows installation, here, so I can't check. Could you test my Testing program ?

-Michael

Reply by email

Unknown author
to Michael Schnell: After your patch, my testing program works OK on GTK2 (doing Synchronize, PostMessage…
Michael Schnell wrote
Bernd What Widget Type do you use ?

I'm using GTK2 (but a very old version of it that came with Ubuntu Hardy, the package manager says version 2.12.9). -------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20110421/aee631ba/attachment.html>

Reply by email

Unknown author
to Michael Schnell
Michael Schnell wrote
But I do suppose you did set "gtk2" there ...

Yes, gtk2.

I have problems compiling against Qt, not only with Lazarus, basically with all kinds of current software, it seems to me that Qt is releasing a new version every other week and is totally breaking compatibility with every minor version number change (at least that is how it appears to me), and all apps linking against it (including Lazarus) are relying on the very latest features the very day after a new Qt is released, so Qt is not an option for me if I have to always deploy hundreds of MB of qt-xyz libs together with my application to make it run on more than only the very latest bleeding edge distributions, so I stopped to even think about using it.

gtk2 has been the only thing that seemed to be constant and stable, no matter which gtk2 app I try to compile against my really old gtk2 (or even already compiled binaries from others) they will just work. At least they did during the last few years.

But this is an entirely different topic...
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20110421/ecce4aec/attachment.html>

Reply by email

Bernd
to Bernd: 2011/4/20 Henry Vermaak : I've done some more testing now. Maybe its my old GTK2 version,…
Bernd wrote
I have tried QueueAsyncCall and Synchronize() both don't work here. PostMessage() works.

I have now done the following to "simulate" a Synchronize() with the help of PostMessage()

This seems to work without problems, without crashing, without noticeable strange behavior and is running smoothly. Is the following usage of RTLeventWaitFor correct or am I abusing/missing something and calling for trouble?

in my worker thread I have:

begin
  GuiHasFinishedEvent := RTLEventCreate;
  while...
  begin
    // wite to the image
    // Image.Picture.Bitmap.RawImage.Data[somewhere] := something;
    // frame is complete, notify GUI
    RTLeventResetEvent(GuiHasFinishedEvent);
    PostMessage(Application.MainForm.Handle, MM_FRAME_COMPLETE, 0, 0);
    RTLeventWaitFor(GuiHasFinishedEvent);
  end;
  RTLeventdestroy(GuiHasFinishedEvent);
end;

and in my Form:

TMainForm = class(TForm)

  procedure OnCameraFrame(var Msg); message MM_FRAME_COMPLETE;
  ...
procedure TMainForm.OnCameraFrame(var Msg);
begin
  // it is alaways in updatig state, only release this for a short moment
  Image.Picture.Bitmap.EndUpdate();
  Image.Picture.Bitmap.BeginUpdate();
  // the camera thread is waiting, notify it that we are done.
  RTLeventSetEvent(GuiHasFinishedEvent);
end;

Reply by email

Michael Schnell
to Bernd: 2011/4/20 Henry Vermaak : I've done some more testing now. Maybe its my old GTK2 version,…
Bernd wrote 6 lines
Maybe its my old GTK2 version, I still have Ubuntu Hardy on my laptop and the GTK2 that came with it (don't know which version exactly, I never ever did anything with GTK directly, only through wrappers like wx, etc., so I don't know much about GTK). I have tried QueueAsyncCall and Synchronize() both don't work here.

Did you try the most recent svn version of LCL ?

PostMessage() and QueueAsyncCall() _should_ work.

-Michael
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20110502/5377aa0f/attachment.html>

Reply by email

Bernd
to Michael Schnell

2011/5/2 Michael Schnell :

PostMessage() and QueueAsyncCall() _should_ work.

PostMessage() works (that is what I currently use) and QueueAsyncCall() did not work when I opened this thread, I will test it again tomorrow.

But what I would need for my application is something like Synchronize(), I need to block my camera thread after every frame until the GUI has updated itself with the newly received frame. Therefore I have now re-implemented the functionality of Synchonize() in the following way:

    // normally I would have used Synchoize() here but this
    // does not work with the really old GTK2 I have here anymore,
    // it would not wake up the GUI thread until I move the mouse.
    // The following 3 lines together with the message method in the
    // main form do exactly the same. It wakes up the GUI thread and
    // waits until it is done.
    RTLeventResetEvent(GuiHasFinishedEvent);
    PostMessage(Application.MainForm.Handle, MM_FRAME_COMPLETE, 0, 0);
    RTLeventWaitFor(GuiHasFinishedEvent);

and in the GUI

TMainForm = Class(TFom)
...

   procedure OnCameraFrame(var Msg); message MM_FRAME_COMPLETE;
   ...

end;

procedure TMainForm.OnCameraFrame(var Msg);
begin
  // it is alaways in updating state, only release this for a short moment
  Display.Picture.Bitmap.EndUpdate();
  Display.Picture.Bitmap.BeginUpdate();
  // the camera thread is waiting, notify it that we are done.
  RTLeventSetEvent(GuiHasFinishedEvent);
end;

This works like a charm.

Reply by email

Michael Schnell
to Bernd
Bernd wrote
PostMessage() works (that is what I currently use) and QueueAsyncCall() did not work when I opened this thread, I will test it again tomorrow.

Thanks. It dopes work for me now, but I am interested is seeing if it does work everywhere.

But what I would need for my application is something like Synchronize(),

Synchronize does work for me (and did work since many months).

After playing with this stuff for a long time, my opinion is that TThread.Synchronize(), PostMessage() (and TThread.Queue() if once someone more knowledgeable might care to implement it) should (at least for non-Windows Widget Types) be done on top of
TApplication.QueueAsyncCall, so that all will work if one does.

I believe you could easily implement TThread.Synchronize in a portable way e.g. by using a TEvent: The thread queues an asynccall and then waits for the event. The asynccall calls the method to be synchronized and the sets the event.

I need to block my camera thread after every frame until the GUI has updated itself with the newly received frame.

That might result in may completely unhandled frames, as the GUI thread might not be able to perform the synchronized methods for a huge amount of time.

So IMHO the better design is to store the data somewhere, set a "buffer not empty" bit and do an AsyncCall. The GUI event resets the bit when it has handled the data in the buffer. When the next frame is received by the thread same checks if the bit is reset (buffer empty)m it acts accordingly, filling the buffer or throwing away the frame.

Double buffering or a buffer FIFO can be implemented in a similar manner (e.g. using a TList of buffer pointers).

-Michael

Reply by email