View Issue Details

IDProjectCategoryView StatusLast Update
0011145LazarusIDEpublic2014-09-10 17:19
ReporterMartin Friebe Assigned ToPaul Ishenin  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Product Version0.9.25 (SVN) 
Target Version1.0.0Fixed in Version1.0.0 
Summary0011145: Please reopen 0008479 => "Always visible caret" option broken [scroll does not refresh display]
DescriptionBug 0008479 has been marked as resolved. Yet It still reproduces on my PC, with the latest SVN version (and also with and any tested SVN version, since it was marked as resolved)

Since I am not the original Reporter of the Bug, I can not add any note to the original Bug, this is why I request the re-opening via a separate Bug.
Additional InformationI also believe that 0010905 is a duplicate (or very close related) of 0008479.

0010905 describes the same/similar behaviour for horizontal scrolling (while the original Bug describes the behaviour for vertical scrolling). From my experience the vertical scrolling issue, only appears if the Unit/Syn-Editor.Width is quite small (eg, only room to display about 10 to 15 chars per line). Thus enabling line-numbers (or changing the display-font size) may be able to affect this. (but enabling line numbers is not the cause of the issue.)
TagsNo tags attached.
Fixed in Revision15455
LazTarget1.0
WidgetsetWin32/Win64
Attached Files

Relationships

duplicate of 0008479 closedMattias Gaertner "Always visible caret" option broken 
related to 0010905 closed Scrolling the Text editor using the Vertical scrollbar (when "Show Line numbers" is active) -> Draw Errors 
related to 0007877 confirmed when moving the mouse over some components they blink 

Activities

Martin Friebe

2008-04-20 18:41

manager   ~0018957

Just a note, due to 0011178 in order to reproduce this Bug, the Caret must be in the visible area, before starting to scroll

Martin Friebe

2008-04-20 19:15

manager   ~0018964

I have done some more research. not finished, but since I may not have enough time, I wanted to share what I have. I believe it does some of the narrowing down. I hope it is of any help.

In synedit.pp I have added a flag
fInUpdateCaret : Integer // init to 0 in constructor

which is set/unset in
procedure TCustomSynEdit.UpdateCaret;
var ....;
begin
  inc(fInUpdateCaret);
  //original code
  dec(fInUpdateCaret);
end;

I found that the bug goes away, if I stop the following call at the end of
procedure TCustomSynEdit.DecPaintLock; { called from SetCarretXY }
....
  if fInUpdateCaret = 0 then begin // My code to prevent calls if in UpdateCaret
    if fStatusChanges <> [] then
      DoOnStatusChange(fStatusChanges);
   end;

So "DoOnStatusChange" can no longer be called, while we are in UpdateCaret.

AFAIK DoOnStatusChange, eventually gets to (ide/main.pp)
procedure TMainIDE.UpdateSaveMenuItemsAndButtons(UpdateSaveAll: boolean);
begin
  GetCurrentUnit(SrcEdit,AnUnitInfo);
  // menu items
  if UpdateSaveAll then
    MainIDEBar.itmProjectSave.Enabled :=
.....

If instead of preventing the initial call of DoOnStatusChange (in Synedi.decPaintLock), I prevent UpdateSaveMenuItemsAndButtons from execution => the bug also goes away.

But if I let "UpdateSaveMenuItemsAndButtons" call "GetCurrentUnit", and only prevent the rest of it from execution => the bug still exists.

======= Conclusion:
Something messes up in "GetCurrentUnit", if called from within TCustomSynEdit.UpdateCaret.

I have not looked any deeper into it, so I can't tell what it is. But I hope, this narrows it down a bit, and will be of some help.

Martin Friebe

2008-05-10 15:54

manager   ~0019327

Update:
The last post is no longer applicable, i done some new test, and something must have changed.

The problem now is, that ide\sourceeditor.pp line 5817 in:
 Procedure TSourceNotebook.UpdateStatusBar;
    Statusbar.Panels[0].Text := PanelXY;

this causes the Statusbar to update (in EndUpdate):
- the bug is not triggered if this is not executed, while in UpdateCarret
- if this is run while in updateCarret, the statusbar does not update neither

So somewhere some calls to the windows APi must be in an order that upsets Windows? I am not an expert on the Win-API, so I can't track it any further.

---
Procedure TSourceNotebook.UpdateStatusBar;
is called from
Procedure TSourceNotebook.EditorChanged(Sender: TObject);
is called from
Procedure TSourceEditor.EditorStatusChanged(Sender: TObject;
which is assigned to SynEdits's OnStatusChange

Martin Friebe

2008-06-14 16:32

manager   ~0020141

Maybe the following can help to track this further:

in lcl\interfaces\win32\win32callback.inc line 395 (function WindowProc)

{$ifdef MSG_DEBUG}
    if useDoubleBuffer and (DoubleBufferDC <> 0) then
    begin
      DebugLn('ERROR: RECURSIVE PROBLEM! DOUBLEBUFFERED PAINT');
      useDoubleBuffer := false;
    end;
{$endif}

If you enable this, then while you scroll it is triggered and prints the message, but ONLY if "always visible carret" is true.

My best guess is this is triggered from inside "TStatusBar.EndUpdate".

Now the issue is, even so the above disables dbl-buffer for the 2nd call of WindowProc, the drawing error persists.
This is because of line 432:
        if ThemeServices.ThemesEnabled then
          PushEraseBkgndCommand(ecDoubleBufferNoRemove);

which dishonours the useDoubleBuffer=False

Modifying this to
        if ThemeServices.ThemesEnabled then
        begin
          if useDoubleBuffer
          then PushEraseBkgndCommand(ecDoubleBufferNoRemove)
          else PushEraseBkgndCommand(ecDefault); // or ecDiscard
        end;


AND IT IS SOLVED => the bug disappears.


So the issue is a nested call to WindowProc, both using the same global DoubleBufferDC.

Yet I am not sure, if fixing it thsi way (detecting the nesting, and disabling DoubleBuffer is the wanted solution. Given that this detection is part of debugging code, this kind of nesting may not at all be wanted. In which case the issue would need addressing at a higher level.


Hope this helps

Paul Ishenin

2008-06-17 09:33

manager   ~0020166

The problem is that StatusBar starts its painting while SynEdit have not exited its paint handler. As result some global variables become incorrect.

Paul Ishenin

2008-06-17 10:19

manager   ~0020167

Please test and close if ok.

Martin Friebe

2008-06-17 22:37

manager   ~0020172

Unfortunately, this change didn't fix it. I am still looking into why this may be. (Not using a DoubleBuffer, in case of re-entry did work, so I don't know why saving and restoring doesn't.)

One think I do not know is, if both or any of the two (Synedit/Statusbar), may need needParentPaint, and if so, if Windows is ok, with getting two (nested) DC for the same parent?

Another thing, but it does not seem to fix it, is, that the old code, re-used the bitmap, therefore it was never freed.
Now if RestoreDoublebuffer is executed, the handle to the bitmap is discarded, without releasing it.

     if CurDoubleBuffer.Bitmap <> 0 then // MFR
          Windows.DeleteObject(CurDoubleBuffer.Bitmap);
before discarding it, in restore bitmap.
The DC, should always been discarded, before Restore is called.

However as I said, even, if I free the bitmap, the bug is still there.

Martin Friebe

2008-06-17 23:29

manager   ~0020173

Sorry my fault

IT DOES WORK OK.

I just messed up my configs, and compiled with an older unit.... sorry about that.

The only thing remaining is to insert something like

    if CurDoubleBuffer.Bitmap <> 0 then // MFR
          Windows.DeleteObject(CurDoubleBuffer.Bitmap);

at the begining of RestoreDoubleBuffer

Martin Friebe

2008-06-17 23:41

manager   ~0020174

Just an idea.

Instead of maintaining a list to keep old records, why not making a local variable

 BackupDC : TDoubleBuffer

and on entry store the current global record in the local variable, and restore from there?

Paul Ishenin

2008-06-18 02:50

manager   ~0020175

Thanks, changed. Please test and close if ok.

Martin Friebe

2008-06-18 09:33

manager   ~0020176

thanks

Issue History

Date Modified Username Field Change
2008-04-13 17:30 Martin Friebe New Issue
2008-04-13 17:30 Martin Friebe Widgetset => Win32
2008-04-13 19:53 Vincent Snijders Relationship added duplicate of 0008479
2008-04-13 19:55 Vincent Snijders LazTarget => 1.0
2008-04-13 19:55 Vincent Snijders Assigned To => Mattias Gaertner
2008-04-13 19:55 Vincent Snijders Status new => assigned
2008-04-13 19:56 Vincent Snijders Relationship added related to 0010905
2008-04-20 18:41 Martin Friebe Note Added: 0018957
2008-04-20 19:15 Martin Friebe Note Added: 0018964
2008-04-24 09:57 Vincent Snijders Target Version => 1.0.0
2008-05-10 15:55 Martin Friebe Note Added: 0019327
2008-06-14 16:32 Martin Friebe Note Added: 0020141
2008-06-17 05:36 Paul Ishenin Assigned To Mattias Gaertner => Paul Ishenin
2008-06-17 09:33 Paul Ishenin Note Added: 0020166
2008-06-17 10:19 Paul Ishenin Fixed in Revision => 15449
2008-06-17 10:19 Paul Ishenin Status assigned => resolved
2008-06-17 10:19 Paul Ishenin Fixed in Version => 1.0.0
2008-06-17 10:19 Paul Ishenin Resolution open => fixed
2008-06-17 10:19 Paul Ishenin Note Added: 0020167
2008-06-17 22:37 Martin Friebe Status resolved => feedback
2008-06-17 22:37 Martin Friebe Resolution fixed => reopened
2008-06-17 22:37 Martin Friebe Note Added: 0020172
2008-06-17 23:29 Martin Friebe Note Added: 0020173
2008-06-17 23:41 Martin Friebe Note Added: 0020174
2008-06-18 02:50 Paul Ishenin Fixed in Revision 15449 => 15455
2008-06-18 02:50 Paul Ishenin Status feedback => resolved
2008-06-18 02:50 Paul Ishenin Resolution reopened => fixed
2008-06-18 02:50 Paul Ishenin Note Added: 0020175
2008-06-18 09:33 Martin Friebe Status resolved => closed
2008-06-18 09:33 Martin Friebe Note Added: 0020176
2014-09-10 17:19 Juha Manninen Relationship added related to 0007877