Carbon has the double-buffered screen display.
For 'instant arbitrary' drawing into a window, one often has to flush
the new drawing to the screen using Carbon functions like
QDFlushPortBuffer() or CGContextFlush().
This can be tricky, because if you are drawing a lot of content, you
don't want to flush after every individual Line or TextOut into a
Canvas. But if you don't ever explicitly flush, then in some cases
the draw to screen is delayed too much (before the Message loop gets
around to flushing the buffers). And in some other cases, you might
NEVER see the drawing, unless you explicitly flush after drawing.
On PC Delphi or Lazarus, if a program decides it is time to draw a
few lines or strings into a paintbox, the changes automatically
display pretty quickly, without having to do anything explicit in the
high-level program to get the screen flushed.
Perhaps Lazarus on Carbon can never be that simple without
sacrificing too much performance, but I'm ignorant of too many issues.
The simplest way to make a Carbon Canvas.LineTo or a Canvas.TextOut
to immediately show on-screen, would be to modify the carbon LCL so
that every canvas draw call will automatically flush the new drawing
to the screen. But in cases where a few hundred lines need to be
drawn quickly, then if every LineTo is followed by a Flush, then the
drawing might get painfully slow.
For instance, I'm currently working on a very simple little 'instant
drawing' task that works great in PC Lazarus, but does not work at
all on Carbon Lazarus.
It is a TPaintBox that contains an audio wave display, with vertical
musical barlines superimposed. If the user clicks one of the
barlines, the TPaintBox MouseDown and MouseMove is supposed to draw a
vertical XOR dotted line, which tracks the mouse position until the
mouse button is released.
This window is too complicated to entirely redraw every time the user
nudges the mouse. Just drawing an XOR moving dotted line looks fine
and is responsive to the mouse. After the user releases the mouse,
the TPaintBox MouseUp will invalidate the paintbox, triggering a
full redraw of the finished edit.
On Carbon, even if you invalidate a TPaintBox to make the OnPaint
event happen-- Sometimes you have to call Application.ProcessMessages
right after the invalidate, or the TPaintBox will not redraw quickly,
and sometimes a TPaintBox will not redraw at all simply by being
invalidated. It seems most reliable to follow an Invalidate by an
Application.ProcessMessages.
Am not bitterly complaining. Am just describing the situation to
solicit discussion of the best way that Carbon LCL should handle
this. I couldn't make a specific feature request right now, because
am not yet certain what feature to request. Ideally an arbitrary
TPaintBox draw would 'just work' on Mac like it does on PC, but maybe
it will never be that simple.
====
I'm having trouble just finding a temporary workaround for this
behavior in Carbon LCL. My LineTo drawing into the TPaintBox,
tracking the mouse, is just not showing up at all, in spite of
numerous experiments. Ordinary drawing inside the TPaintBox.OnPaint
is working fine, but the 'arbitrary drawing' during a Mouse Down or
Mouse Move never makes it to the screen.
If I can get 'arbitrary drawing' to work in the MouseDown/MouseMove
events, it might provide info about how to change LCL to more easily
show the drawing.
Here is the kind of simple drawing that is done in the
TPaintBox.MouseMove:
NotesPB.Canvas.Pen.Mode := pmXOr;
NotesPB.Canvas.Pen.Style := psDot;
NotesPB.Canvas.Pen.Color := clBlack;
NotesPB.Canvas.Brush.Color := clwhite;
NotesPB.Canvas.MoveTo(CurMouseMoveBarTrackPixel, 0); //erase old
line
NotesPB.Canvas.LineTo(CurMouseMoveBarTrackPixel, NotesPB.height);
NotesPB.Canvas.MoveTo(CurMouseMoveBarTrackPixel + 1, 0);
NotesPB.Canvas.LineTo(CurMouseMoveBarTrackPixel + 1,
NotesPB.height);
CurMouseMoveBarTrackPixel := X;
NotesPB.Canvas.MoveTo(CurMouseMoveBarTrackPixel, 0); //draw new
line
NotesPB.Canvas.LineTo(CurMouseMoveBarTrackPixel, NotesPB.height);
NotesPB.Canvas.MoveTo(CurMouseMoveBarTrackPixel + 1, 0);
NotesPB.Canvas.LineTo(CurMouseMoveBarTrackPixel + 1,
NotesPB.height);
Have tried disabling the pmXOr and psDot, to make sure that isn't
making a problem, but it won't draw to the screen even if using
pmCopy and psSolid pen properties.
Have tried manually flushing the screen after these draw commands
using both CGContextFlush and QDFlushPortBuffer, but even inserting
those explicit Carbon commands doesn't make the drawing appear
onscreen. So maybe the drawing is going somewhere that needs more
processing before a Flush command even knows about it?
Or perhaps the Clipping Region is nil, or the Clipping Region just
doesn't happen to include where the code wants to draw? If there a
preferred high-level Lazarus method of setting the Clipping Region in
a TPaintBox or its Canvas?
Searching Carbon LCL, I find no instance of QDFlushPortBuffer, and
one only instance of CGContextFlush, in carbonobject.inc, procedure
TCarbonWidgetSet.DCRedraw().
The only place that DCRedraw is called, is from
TCanvas.RealizeAutoDraw in canvas.inc. Tracing the code, it looks
like RealizeAutoDraw would only get called when SetAutoRedraw is
called, and SetAutoRedraw is apparently never called except in
response to setting the property TCanvas.AutoRedraw to TRUE.
In other words, if this is intended to be a method of flushing the
screen, the only way to 'get to' that CGContextFlush call, would be
to always follow drawing commands with "Canvas.AutoRedraw := True;"
I tried that too, but it doesn't make any changes show on the screen.
So maybe the Carbon Clipping Region is wrong when the drawing happens.
I don't know what AutoRedraw is exactly supposed to do. Am mostly
familiar with Delphi, and to my knowledge AutoRedraw is not a TCanvas
property in Delphi. I couldn't web-search a specification of what
AutoRedraw is supposed to do in Lazarus.
If AutoRedraw is supposed to make Lazarus automatically flush to the
screen after each individual draw operation, and if this worked as
advertised, that might be a good generic solution to the kind of
issue I'm seeing here.
Thanks, and apologies for such a long confused message.
jcjr
_________________________________________________________________
To unsubscribe: mail [EMAIL PROTECTED] with
"unsubscribe" as the Subject
archives at http://www.lazarus.freepascal.org/mailarchives