Le 17/04/2018 à 11:52, Jean-Marc Lasgouttes a écrit :
Sorry for being slow on this. As I understand it, the crash is related
to the new painting architecture and therefore probably exists in 2.3.x
too. This is the one I need to fix first. I have an idea, but I have to
see how it works. This should fix the cursor issues with spanish
keyboard that Scott reported.
Please test this experimental patch. It should cure the crash.
Scott, I would be interested to know whether you can still reproduce the
Spanish keyboard issue.
JMarc
From 65b7c5f62f586f3353c89326ea26d5aa8d9353eb Mon Sep 17 00:00:00 2001
From: Jean-Marc Lasgouttes <lasgout...@lyx.org>
Date: Wed, 18 Apr 2018 10:10:08 +0200
Subject: [PATCH] Rework caret display code
The new code is much simpler: what it does is, after redrawing has
been done, to mark the cursor row as changed, so that it will be
repainted on next paint event.
This avoids some crashes at the price of possibly repainting the row
when it was not necessary.
---
src/BufferView.cpp | 59 +++++++++--------------------------------------------
src/BufferView.h | 3 ---
src/TextMetrics.cpp | 3 +--
3 files changed, 11 insertions(+), 54 deletions(-)
diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index 27176b3..5f61ef7 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -238,7 +238,7 @@ struct BufferView::Private
last_inset_(0), clickable_inset_(false),
mouse_position_cache_(),
bookmark_edit_position_(-1), gui_(0),
- horiz_scroll_offset_(0), repaint_caret_row_(false)
+ horiz_scroll_offset_(0)
{
xsel_cache_.set = false;
}
@@ -317,12 +317,6 @@ struct BufferView::Private
/// a slice pointing to the start of the row where cursor was
/// at previous draw event
CursorSlice last_row_slice_;
-
- /// a slice pointing to where the cursor has been drawn after the current
- /// draw() call.
- CursorSlice caret_slice_;
- /// indicates whether the caret slice needs to be repainted in this draw() run.
- bool repaint_caret_row_;
};
@@ -3069,29 +3063,6 @@ void BufferView::setCurrentRowSlice(CursorSlice const & rowSlice)
}
-namespace {
-
-bool sliceInRow(CursorSlice const & cs, Text const * text, Row const & row)
-{
- /* The normal case is the last line. The previous line takes care
- * of empty rows (e.g. empty paragraphs). Cursor boundary issues
- * are taken care of when setting caret_slice_ in
- * BufferView::draw.
- */
- return !cs.empty() && cs.text() == text && cs.pit() == row.pit()
- && ((row.pos() == row.endpos() && row.pos() == cs.pos())
- || (row.pos() <= cs.pos() && cs.pos() < row.endpos()));
-}
-
-}
-
-
-bool BufferView::needRepaint(Text const * text, Row const & row) const
-{
- return d->repaint_caret_row_ && sliceInRow(d->caret_slice_, text, row);
-}
-
-
void BufferView::checkCursorScrollOffset()
{
CursorSlice rowSlice = d->cursor_.bottom();
@@ -3163,16 +3134,6 @@ void BufferView::draw(frontend::Painter & pain, bool paint_caret)
int const y = tm.first().second->position();
PainterInfo pi(this, pain);
- /** A repaint of the previous caret row is needed if there is
- * caret painted on screen and either
- * 1/ a new caret has to be painted at a place different from
- * the existing one;
- * 2/ there is no need for a caret anymore.
- */
- d->repaint_caret_row_ = !d->caret_slice_.empty() &&
- ((paint_caret && d->cursor_.top() != d->caret_slice_)
- || ! paint_caret);
-
// Check whether the row where the cursor lives needs to be scrolled.
// Update the drawing strategy if needed.
checkCursorScrollOffset();
@@ -3188,7 +3149,7 @@ void BufferView::draw(frontend::Painter & pain, bool paint_caret)
if (pain.isNull()) {
pi.full_repaint = true;
tm.draw(pi, 0, y);
- } else if (d->repaint_caret_row_) {
+ } else {
pi.full_repaint = false;
tm.draw(pi, 0, y);
}
@@ -3262,15 +3223,15 @@ void BufferView::draw(frontend::Painter & pain, bool paint_caret)
d->update_flags_ = Update::None;
}
- // Remember what has just been done for the next draw() step
+ // If a caret has to be painted, mark its text row as dirty to
+ //make sure that it will be repainted on next redraw.
+ /* FIXME: investigate whether this can be avoided when the cursor did not
+ * move at all
+ */
if (paint_caret) {
- d->caret_slice_ = d->cursor_.top();
- if (d->caret_slice_.pos() > 0
- && (d->cursor_.boundary()
- || d->caret_slice_.pos() == d->caret_slice_.lastpos()))
- --d->caret_slice_.pos();
- } else
- d->caret_slice_ = CursorSlice();
+ Row const & caret_row = d->cursor_.textRow();
+ caret_row.changed(true);
+ }
}
diff --git a/src/BufferView.h b/src/BufferView.h
index fd4ae4c..0381b6b 100644
--- a/src/BufferView.h
+++ b/src/BufferView.h
@@ -138,9 +138,6 @@ public:
/// Only to be called with good y coordinates (after a bv::metrics)
bool needsFitCursor() const;
- /// returns true if this row needs to be repainted (to erase caret)
- bool needRepaint(Text const * text, Row const & row) const;
-
// Returns the amount of horizontal scrolling applied to the
// top-level row where the cursor lies
int horizScrollOffset() const;
diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index efa6d25..d23c09d 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -1891,8 +1891,7 @@ void TextMetrics::drawParagraph(PainterInfo & pi, pit_type const pit, int const
// has row changed since last paint?
bool row_has_changed = row.changed()
- || bv_->hadHorizScrollOffset(text_, pit, row.pos())
- || bv_->needRepaint(text_, row);
+ || bv_->hadHorizScrollOffset(text_, pit, row.pos());
// Take this opportunity to spellcheck the row contents.
if (row_has_changed && pi.do_spellcheck && lyxrc.spellcheck_continuously) {
--
2.7.4