commit fa4fc6fc4d97f5c3d3e8ba44ad8b52f750293623
Author: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date:   Thu Nov 23 15:38:17 2017 +0100

    Avoid some caret ghosts
    
    When the caret is at end of row, if may happen that it is drawn after
    the end of the row. In this case caret blinking will not work
    properly. This patch extends the row background on the left and right
    by Inset::TEXT_TO_INSET_OFFSET. This is only a hack that will not work
    if the caret has a ridiculous width like 6.
    
    Additionally, introduce some (disabled) debug code that numbers the
    rows on screen by painting order.
    
    Finally, make the code that detects whether the caret was in a given
    row more precise (take boundary into account).
    
    Fixes (mostly, see above) bug #10797.
    
    (cherry picked from commit e64ea3576c4534fc647a74d1c9f5e67db39ef783)
---
 src/BufferView.cpp  |    8 +++++---
 src/TextMetrics.cpp |   27 +++++++++++++++++++++++++--
 2 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index 4e2428d..acde1ce 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -2979,7 +2979,7 @@ namespace {
 bool sliceInRow(CursorSlice const & cs, Text const * text, Row const & row)
 {
        return !cs.empty() && cs.text() == text && cs.pit() == row.pit()
-               && row.pos() <= cs.pos() && cs.pos() <= row.endpos();
+               && row.pos() <= cs.pos() && cs.pos() < row.endpos();
 }
 
 }
@@ -3162,9 +3162,11 @@ void BufferView::draw(frontend::Painter & pain, bool 
paint_caret)
        }
 
        // Remember what has just been done for the next draw() step
-       if (paint_caret)
+       if (paint_caret) {
                d->caret_slice_ = d->cursor_.top();
-       else
+               if (d->cursor_.boundary())
+                       --d->caret_slice_.pos();
+       } else
                d->caret_slice_ = CursorSlice();
 }
 
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index 1f4516f..42637d7 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -45,6 +45,7 @@
 #include "frontends/Painter.h"
 #include "frontends/NullPainter.h"
 
+#include "support/convert.h"
 #include "support/debug.h"
 #include "support/lassert.h"
 
@@ -1917,8 +1918,16 @@ void TextMetrics::drawParagraph(PainterInfo & pi, 
pit_type const pit, int const
                        LYXERR(Debug::PAINTING, "Clear rect@("
                               << max(row_x, 0) << ", " << y - row.ascent() << 
")="
                               << width() << " x " << row.height());
-                       pi.pain.fillRectangle(max(row_x, 0), y - row.ascent(),
-                               width(), row.height(), pi.background_color);
+                       // FIXME: this is a hack. We know that at least this
+                       // amount of pixels can be cleared on right and left.
+                       // Doing so gets rid of caret ghosts when the cursor is 
at
+                       // the begining/end of row. However, it will not work if
+                       // the caret has a ridiculous width like 6. (see ticket
+                       // #10797)
+                       pi.pain.fillRectangle(max(row_x, 0) - 
Inset::TEXT_TO_INSET_OFFSET,
+                                             y - row.ascent(),
+                                             width() + 2 * 
Inset::TEXT_TO_INSET_OFFSET,
+                                             row.height(), 
pi.background_color);
                }
 
                // Instrumentation for testing row cache (see also
@@ -1956,6 +1965,20 @@ void TextMetrics::drawParagraph(PainterInfo & pi, 
pit_type const pit, int const
                                      row_x + row.right_x() > bv_->workWidth());
                y += row.descent();
 
+#if 0
+               // This debug code shows on screen which rows are repainted.
+               // FIXME: since the updates related to caret blinking restrict
+               // the painter to a small rectangle, the numbers are not
+               // updated when this happens. Change the code in
+               // GuiWorkArea::Private::show/hideCaret if this is important.
+               static int count = 0;
+               ++count;
+               FontInfo fi(sane_font);
+               fi.setSize(FONT_SIZE_TINY);
+               fi.setColor(Color_red);
+               pi.pain.text(row_x, y, convert<docstring>(count), fi);
+#endif
+
                // Restore full_repaint status.
                pi.full_repaint = tmp;
 

Reply via email to