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

Reply via email to