View Issue Details

IDProjectCategoryView StatusLast Update
0021929LazarusOtherpublic2012-05-05 21:04
ReporterJanusz Tomczak Assigned ToMartin Friebe  
Status closedResolutionfixed 
OSUbuntu 10.04, Wine 1.4 
Product Version1.1 (SVN) 
Target Version1.0.0Fixed in Version1.1 (SVN) 
Summary0021929: SynEdit - Caret paint error when pressed Enter key
DescriptionPlease see the attached video.
After scroll, caret visible only in lines 100 and 1000.
Sorry for my bad english.

OS: Ubuntu 10.04, Wine 1.4
TagsNo tags attached.
Fixed in Revision37166
Attached Files


2012-05-03 12:13


2012-05-03 12:15 (369,039 bytes)

Martin Friebe

2012-05-03 23:06

manager   ~0059222

Last edited: 2012-05-03 23:09

I do not have Wine, but I did tests on win-vista and win-2000. It seems this may be a bug in Wine. However maybe it can be improved.

Looking at the video, shows 2 problems:
1) The old caret is not removed (and therefore is scrolled up). Note: it is not repainted, scroll just copies the existing pixels a few lines up.
2) The new caret is not pointed on the new line.

About 2:
This is actually normal.
If an application is to slow, certain paint events are skipped. In this case the painting of the caret.
Once you let the return key go, the new caret will (should) appear (while the old may still exist as static line)

On most windows thinks are fast enough, so this does not happen. (Scrolling is quite fast, but of course depends on your PC).
On wine, everything is emulated. So this may be slow enough to keep the new caret from painting. (test , by sending enter keys at lower frequency)

I have simulated this on windows, by adding artificial slowdown to the code, and got the same result (new caret not shown, as long as return is kept down)

So this is normal. To enforce painting would increase CPU usage unreasonable, and slow down the system.

About 1:
This is probably a wine issue.

SynEdit uses ScrollWindowEx to move the existing text up or down.
On both windows systems I had this function hides the caret, so the caret does not appear in the moved image (text). My *assumption* is, that wine does not do this.

I could not actual find documentation about this. Only tested under vista and 2000. But if indeed all Windows do this and wine does not, then I consider it a bug in Wine.

The line 100, 1000 is because the gutter width changes, so instead of scrolling synedit does a full repaint.

By the way, please look at 0021924, does that happen to you to (on wine, using Lazarus SVN trunk or 1.1 snapshot with rev > 37141)?
Because this also relies on BeginPaint and EndPaint doing the caret hiding (they do on windows, but I do not know about wine)

Testing confirming my suspicions. (You can skip them, and go to testing the patch below)

synedit.pp line 4187:
      if ScrollWindowEx(Handle, 0, LineHeight * Delta, @srect, @srect, 0, nil, SW_INVALIDATE)
      then begin

Set a breakpoint on the line before this.
Then enter a return on the last line (so the editor will scroll up). Try to time it, so the caret is visible at this time.
The breakpoint will be reached. If the caret is not visible, hit F9 and try again.

Having reached the breakpoint with the caret visible. At this time the editor has NOT yet scrolled.
Single step. When you execute this line most of he editor scrolls (except for the last 1 or 2 lines / watch the line numbers, there will be the same line number on 2 lines).
At this time the caret should be hidden.

If it is not hidden, Then this is bad behaviour in wine....

If it has not scrolled at all, then maybe the emulation defers this (as GTK also does deferred scrolling)

The "IF" condition should be true. The next line should be
        include(fStateFlags, sfHasScrolled);

If it goes to "Invalidate" instead, then something else is wrong....

Trying a patch to avoid the problew (issue "1" from the 2 issues)

Since the Caret needs to be hidden anyway, we can do that explicit. This should use almost no time/resources, so it should not cause problems. (And worked fine on my tests for win and gtk)

synedit.pp line 4186:
      srect.Bottom := FTextArea.TextBounds.Bottom;
      if ScrollWindowEx(Handle, 0, LineHeight * Delta, @srect, @srect, 0, nil, SW_INVALIDATE)
      then begin

insert "FScreenCaret.Hide;", so you get:
      srect.Bottom := FTextArea.TextBounds.Bottom;
      if ScrollWindowEx(Handle, 0, LineHeight * Delta, @srect, @srect, 0, nil, SW_INVALIDATE)
      then begin
Open package SynEdit, recompile, test...

Let me know if it improves anything.

Do not worry about showing it, this is already taken care of.

Martin Friebe

2012-05-03 23:21

manager   ~0059223

What version / date is your wine?

Zeljan Rikalo

2012-05-04 07:52

developer   ~0059231

Any wine below 1.5 can have such problems.

Janusz Tomczak

2012-05-04 18:37

reporter   ~0059234

Wine 1.4, March 7, 2012.
The patch "FScreenCaret.Hide" not resolving problem.

Janusz Tomczak

2012-05-04 18:45

reporter   ~0059235

The old caret is hidden, when I used FScreenCaret.Visible:=False

Martin Friebe

2012-05-04 19:58

manager   ~0059238

But FScreenCaret.Visible:=False is permanent. The caret will not be displayed again, until you move focus away, and back to the SynEdit. (at least on none Wine)

Can you try this.
- use FScreenCaret.Visible:=False as you tried
- line 3495, in "procedure TCustomSynEdit.Paint;" is currently:
    UpdateCaret; // Todo: only ShowCaret() .....
  In front of this line add

This will have side effects, like the caret being shown, even on an unfocused editor, or in design mode....
But ignoring those, if you scroll (press return), will the caret be hidden (or shown on the last line where it should be) AND be visible after releasing the enter key?

Janusz Tomczak

2012-05-04 21:01

reporter   ~0059240

Result: Same as attached video.

Martin Friebe

2012-05-04 22:57

manager   ~0059242

Then I see no way to fix the issue. The caret must eventually be made visible again.

You can try to make it visible in paint, but *after* "UpdateCaret".

If that does not work either, then there are various other things you can try in your copy. But none of the following will be added to SynEdit as fix. They all degrade (not necessarily much, but to some extend) the performance. And since the bug seems to be in Wine, they will not be added.
Those are *instead* of the "FScreenCaret.Hide".

- Before "ScrollWindowEx" insert:

- Worst solution. Remove "ScrollWindowEx" and always call "Invalidate()" (else block)

Janusz Tomczak

2012-05-05 10:32

reporter   ~0059248

Yes, the bug seems to be in Wine. In Windows it's OK.
"Worst solution. Remove "ScrollWindowEx" and always call "Invalidate()" (else block)" it's fixed this bug.

Martin Friebe

2012-05-05 20:38

manager   ~0059271

Actually I found a way to fix it.

Please test.

Wine does not (as I assumed) scroll the visual representation (pixels on screen) of the caret. But instead Wine does (when ScrollWindowEx is used) update the stored coordinates of the caret.

SynEdit now enforces setting them again, after every scroll.

Janusz Tomczak

2012-05-05 21:04

reporter   ~0059272

Yes, it's fixed this bug. Thank You.

Issue History

Date Modified Username Field Change
2012-05-03 12:13 Janusz Tomczak New Issue
2012-05-03 12:13 Janusz Tomczak File Added: SynEditBug2.ogv
2012-05-03 12:15 Janusz Tomczak File Added:
2012-05-03 12:42 Martin Friebe Status new => assigned
2012-05-03 12:42 Martin Friebe Assigned To => Martin Friebe
2012-05-03 23:06 Martin Friebe LazTarget => -
2012-05-03 23:06 Martin Friebe Note Added: 0059222
2012-05-03 23:06 Martin Friebe Status assigned => feedback
2012-05-03 23:08 Martin Friebe Note Edited: 0059222
2012-05-03 23:09 Martin Friebe Note Edited: 0059222
2012-05-03 23:21 Martin Friebe Note Added: 0059223
2012-05-04 07:52 Zeljan Rikalo Note Added: 0059231
2012-05-04 18:37 Janusz Tomczak Note Added: 0059234
2012-05-04 18:45 Janusz Tomczak Note Added: 0059235
2012-05-04 19:58 Martin Friebe Note Added: 0059238
2012-05-04 21:01 Janusz Tomczak Note Added: 0059240
2012-05-04 22:57 Martin Friebe Note Added: 0059242
2012-05-05 10:32 Janusz Tomczak Note Added: 0059248
2012-05-05 20:38 Martin Friebe Fixed in Revision => 37166
2012-05-05 20:38 Martin Friebe LazTarget - => 1.0
2012-05-05 20:38 Martin Friebe Status feedback => resolved
2012-05-05 20:38 Martin Friebe Fixed in Version => 1.1 (SVN)
2012-05-05 20:38 Martin Friebe Resolution open => fixed
2012-05-05 20:38 Martin Friebe Note Added: 0059271
2012-05-05 20:38 Martin Friebe Target Version => 1.0.0
2012-05-05 21:04 Janusz Tomczak Note Added: 0059272
2012-05-05 21:04 Janusz Tomczak Status resolved => closed