SynEdit: Internal caret (multi caret / custom-color caret) wait for Paint event. Avoid moving/painting the internal caret onto outdated text.

This commit is contained in:
Martin 2022-03-29 14:50:48 +02:00
parent fed01f0513
commit f5e70a4f0b
2 changed files with 26 additions and 1 deletions

View File

@ -2979,6 +2979,7 @@ begin
{$IFDEF VerboseSynEditInvalidate} {$IFDEF VerboseSynEditInvalidate}
DebugLnExit(['TCustomSynEdit.InvalidateGutterLines ',DbgSName(self)]); DebugLnExit(['TCustomSynEdit.InvalidateGutterLines ',DbgSName(self)]);
{$ENDIF} {$ENDIF}
FScreenCaret.WaitForPaint;
end; end;
end; end;
@ -3005,6 +3006,7 @@ begin
{$IFDEF VerboseSynEditInvalidate} {$IFDEF VerboseSynEditInvalidate}
DebugLnExit(['TCustomSynEdit.InvalidateTextLines ',DbgSName(self)]); DebugLnExit(['TCustomSynEdit.InvalidateTextLines ',DbgSName(self)]);
{$ENDIF} {$ENDIF}
FScreenCaret.WaitForPaint;
end; end;
end; end;

View File

@ -462,6 +462,7 @@ type
procedure FinishScroll(dx, dy: Integer; const rcScroll, rcClip: TRect; Success: Boolean); virtual; procedure FinishScroll(dx, dy: Integer; const rcScroll, rcClip: TRect; Success: Boolean); virtual;
procedure BeginPaint(rcClip: TRect); virtual; procedure BeginPaint(rcClip: TRect); virtual;
procedure FinishPaint(rcClip: TRect); virtual; procedure FinishPaint(rcClip: TRect); virtual;
procedure WaitForPaint; virtual;
public public
constructor Create(AHandleOwner: TWinControl; AOwner: TSynEditScreenCaret); constructor Create(AHandleOwner: TWinControl; AOwner: TSynEditScreenCaret);
function CreateCaret(w, h: Integer): Boolean; virtual; function CreateCaret(w, h: Integer): Boolean; virtual;
@ -515,6 +516,7 @@ type
FState: TPainterStates; FState: TPainterStates;
FCanPaint: Boolean; FCanPaint: Boolean;
FInRect: TIsInRectState; FInRect: TIsInRectState;
FWaitForPaint: Boolean;
function dbgsIRState(s: TIsInRectState): String; function dbgsIRState(s: TIsInRectState): String;
procedure DoTimer(Sender: TObject); procedure DoTimer(Sender: TObject);
@ -535,6 +537,7 @@ type
procedure FinishScroll(dx, dy: Integer; const rcScroll, rcClip: TRect; Success: Boolean); override; procedure FinishScroll(dx, dy: Integer; const rcScroll, rcClip: TRect; Success: Boolean); override;
procedure BeginPaint(rcClip: TRect); override; procedure BeginPaint(rcClip: TRect); override;
procedure FinishPaint(rcClip: TRect); override; procedure FinishPaint(rcClip: TRect); override;
procedure WaitForPaint; override;
public public
destructor Destroy; override; destructor Destroy; override;
function CreateCaret(w, h: Integer): Boolean; override; function CreateCaret(w, h: Integer): Boolean; override;
@ -616,6 +619,7 @@ type
procedure FinishScroll(dx, dy: Integer; const rcScroll, rcClip: TRect; Success: Boolean); procedure FinishScroll(dx, dy: Integer; const rcScroll, rcClip: TRect; Success: Boolean);
procedure BeginPaint(rcClip: TRect); procedure BeginPaint(rcClip: TRect);
procedure FinishPaint(rcClip: TRect); procedure FinishPaint(rcClip: TRect);
procedure WaitForPaint;
procedure Lock; procedure Lock;
procedure UnLock; procedure UnLock;
procedure AfterPaintEvent; // next async procedure AfterPaintEvent; // next async
@ -3168,6 +3172,11 @@ begin
FInPaint := False; FInPaint := False;
end; end;
procedure TSynEditScreenCaretPainter.WaitForPaint;
begin
//
end;
{ TSynEditScreenCaretPainterSystem } { TSynEditScreenCaretPainterSystem }
procedure TSynEditScreenCaretPainterSystem.BeginScroll(dx, dy: Integer; procedure TSynEditScreenCaretPainterSystem.BeginScroll(dx, dy: Integer;
@ -3271,7 +3280,9 @@ var
l: Integer; l: Integer;
am: TAntialiasingMode; am: TAntialiasingMode;
begin begin
if ForcePaintEvents and (not FInPaint) then begin if (ForcePaintEvents and (not FInPaint)) or
FWaitForPaint
then begin
Invalidate; Invalidate;
exit; exit;
end; end;
@ -3476,6 +3487,7 @@ begin
FInRect := IsInRect(rcClip); FInRect := IsInRect(rcClip);
FCanPaint := FInRect = irInside; FCanPaint := FInRect = irInside;
FWaitForPaint := False;
if (psCleanOld in FState) and not FCanPaint then begin if (psCleanOld in FState) and not FCanPaint then begin
if IsInRect(rcClip, FOldX, FOldY, FOldW, FOldH) <> irInside then begin if IsInRect(rcClip, FOldX, FOldY, FOldW, FOldH) <> irInside then begin
@ -3514,6 +3526,12 @@ begin
FCanPaint := True; FCanPaint := True;
end; end;
procedure TSynEditScreenCaretPainterInternal.WaitForPaint;
begin
inherited WaitForPaint;
FWaitForPaint := True;
end;
destructor TSynEditScreenCaretPainterInternal.Destroy; destructor TSynEditScreenCaretPainterInternal.Destroy;
begin begin
assert(not(FInPaint or FInScroll), 'TSynEditScreenCaretPainterInternal.Destroy: not(FInPaint or FInScroll)'); assert(not(FInPaint or FInScroll), 'TSynEditScreenCaretPainterInternal.Destroy: not(FInPaint or FInScroll)');
@ -3653,6 +3671,11 @@ begin
Painter.FinishPaint(rcClip); Painter.FinishPaint(rcClip);
end; end;
procedure TSynEditScreenCaret.WaitForPaint;
begin
FCaretPainter.WaitForPaint;
end;
procedure TSynEditScreenCaret.Hide; procedure TSynEditScreenCaret.Hide;
begin begin
HideCaret; HideCaret;