From 99a67d1fdbcc95e5545f734b7f416b23d79bb989 Mon Sep 17 00:00:00 2001 From: maxim Date: Thu, 22 Nov 2018 22:21:36 +0000 Subject: [PATCH] Merged revision(s) 59584 #e5a2420d88, 59596 #f435a9dc89 from trunk: SynEdit: fix caret blinking during code-completion drop down, if persistent-caret-is-none-blinking ........ SynEdit: (Win10 issue only) fix for "ghost" images of text-caret on Windows 10, in certain conditions where part of the editor is outside the physical screen. ........ git-svn-id: branches/fixes_2_0@59629 - --- components/synedit/syncompletion.pas | 14 ++++++++---- components/synedit/synedit.pp | 33 ++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/components/synedit/syncompletion.pas b/components/synedit/syncompletion.pas index bb56556fdd..8048f2a53f 100644 --- a/components/synedit/syncompletion.pas +++ b/components/synedit/syncompletion.pas @@ -264,7 +264,7 @@ type private FAutoUseSingleIdent: Boolean; Form: TSynBaseCompletionForm; - FAddedPersistentCaret: boolean; + FAddedPersistentCaret, FChangedNoneBlink: boolean; FOnExecute: TNotifyEvent; FWidth: Integer; function GetCaseSensitive: boolean; @@ -1458,6 +1458,7 @@ begin //Todo: This is dangerous, if other plugins also change/changed the flag. FAddedPersistentCaret := False; + FChangedNoneBlink := False; CurrentString := s; if Assigned(OnExecute) then @@ -1474,8 +1475,11 @@ begin if (Form.CurrentEditor is TCustomSynEdit) then begin CurSynEdit:=TCustomSynEdit(Form.CurrentEditor); FAddedPersistentCaret := not(eoPersistentCaret in CurSynEdit.Options); + FChangedNoneBlink := (eoPersistentCaretStopBlink in CurSynEdit.Options2); if FAddedPersistentCaret then CurSynEdit.Options:=CurSynEdit.Options+[eoPersistentCaret]; + if FChangedNoneBlink then + CurSynEdit.Options2:=CurSynEdit.Options2-[eoPersistentCaretStopBlink]; end; Form.SetBounds(x,y,Form.Width,Form.Height); Form.Show; @@ -1713,11 +1717,13 @@ procedure TSynBaseCompletion.Deactivate; var CurSynEdit: TCustomSynEdit; begin - if FAddedPersistentCaret and - (Form<>nil) and (Form.CurrentEditor is TCustomSynEdit) + if (Form<>nil) and (Form.CurrentEditor is TCustomSynEdit) then begin CurSynEdit:=TCustomSynEdit(Form.CurrentEditor); - CurSynEdit.Options:=CurSynEdit.Options-[eoPersistentCaret]; + if FAddedPersistentCaret then + CurSynEdit.Options:=CurSynEdit.Options-[eoPersistentCaret]; + if FChangedNoneBlink then + CurSynEdit.Options2:=CurSynEdit.Options2+[eoPersistentCaretStopBlink]; end; if Assigned(Form) then Form.Deactivate; end; diff --git a/components/synedit/synedit.pp b/components/synedit/synedit.pp index 8b49851372..f28fd549f8 100644 --- a/components/synedit/synedit.pp +++ b/components/synedit/synedit.pp @@ -61,6 +61,35 @@ unit SynEdit; // gtk2.12 paints faster directly {$ENDIF} +{$IFDEF Windows} + (* * On Windows 10 there is an issue, where under certain conditions a "ghost" of the text caret remains visible. + That is one or a series of vertical black lines remain on the screen. + * This can be reproduced, by moving part (eg bottom) of editor off screen (not just behind the taskbar, but + off screen). Then press caret down to scroll. Ghost carets will scroll in with the new text. + Similar move caret to a place off-screen, unfocus editor, and refocus by clicking into the editor (move caret + while setting focus). + To reproduce, the editor must have a visible gutter; and must not have "current line" highlight. + * The conditions to cause this: + - Caret must be in part of editor that is outside the screen. + - Carte must be destroyed (maybe only hidden?), or ScrollWindowEx must affect caret + - Caret must be in a part of the editor for which NO call to "invalidate" was made, + but which will be repainted. + E.g. the gutter, but not the line area received an invalidate, and another line above/below was invalidated + (can happen through ScrollWindowEx). -> In this case the paint message receives a rect, that contains the caret, + even though the part containing the caret was never explicitly invalidated. + If this happens, while the caret is on screen (even if hidden behind another window/taskbar) then all works ok. + But if the caret was off screen, a permanent image of the caret will remain (once scrolled/moved into the screen area). + It seem that in this case windows does not update the information, that the caret became "invisible" when paint did paint + over it. So if the already overpainted caret, is later (by Windows) attempted to be hidden by a final "xor", then it actually + is made permanently visible. + + As a solution, in the above conditions, the full line (actually the text part with the caret) must be invalidated too. + Since this is hard to track, the workaround will invalidate the full line, in any case that potentially could meet the + conditions + *) + {$DEFINE Windows10GhostCaretIssue} +{$ENDIF} + interface { $DEFINE SYNSCROLLDEBUG} @@ -2823,6 +2852,10 @@ begin {$IFDEF VerboseSynEditInvalidate} DebugLnEnter(['TCustomSynEdit.InvalidateGutterLines ',DbgSName(self), ' FirstLine=',FirstLine, ' LastLine=',LastLine]); {$ENDIF} + {$IFDEF Windows10GhostCaretIssue} + if (FLeftGutter.Visible or FRightGutter.Visible) and (sfCaretChanged in fStateFlags) then + InvalidateLines(FirstLine, LastLine); + {$ENDIF} if (FirstLine = -1) and (LastLine = -1) then begin FPaintArea.InvalidateGutterLines(-1, -1); end else begin