last_inset_(0), clickable_inset_(false),
mouse_position_cache_(),
bookmark_edit_position_(-1), gui_(0),
- horiz_scroll_offset_(0)
+ horiz_scroll_offset_(0), repaint_caret_row_(false)
{
xsel_cache_.set = false;
}
/// 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_;
};
// this is the "nodraw" drawing stage: only set the positions of the
// insets in metrics cache.
frontend::NullPainter np;
- draw(np);
+ draw(np, false);
}
}
+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();
+}
+
+}
+
+
+bool BufferView::needRepaint(Text const * text, Row const & row) const
+{
+ return d->repaint_caret_row_ && sliceInRow(d->caret_slice_, text, row);
+}
+
+
void BufferView::checkCursorScrollOffset(PainterInfo & pi)
{
CursorSlice rowSlice = d->cursor_.bottom();
}
-void BufferView::draw(frontend::Painter & pain)
+void BufferView::draw(frontend::Painter & pain, bool paint_caret)
{
if (height_ == 0 || width_ == 0)
return;
int const y = tm.first().second->position();
PainterInfo pi(this, pain);
+ CursorSlice const & bottomSlice = d->cursor_.bottom();
+ /** A repaint of the previous cursor row is needed if
+ * 1/ the caret will be painted and is is not the same than the
+ * already painted one;
+ * 2/ the caret will not be painted, but there is already one on
+ * screen.
+ */
+ d->repaint_caret_row_ = (paint_caret && bottomSlice != d->caret_slice_)
+ || (! paint_caret && !d->caret_slice_.empty());
+
// Check whether the row where the cursor lives needs to be scrolled.
// Update the drawing strategy if needed.
checkCursorScrollOffset(pi);
// however, the different coordinates of insets and paragraphs
// needs to be updated.
LYXERR(Debug::PAINTING, "Strategy: NoScreenUpdate");
- pi.full_repaint = true;
- if (pain.isNull())
+ pi.full_repaint = false;
+ if (pain.isNull()) {
+ pi.full_repaint = true;
+ tm.draw(pi, 0, y);
+ } else if (d->repaint_caret_row_) {
+ pi.full_repaint = false;
tm.draw(pi, 0, y);
+ }
break;
case SingleParUpdate:
}
LYXERR(Debug::PAINTING, "Found new anchor pit = " << d->anchor_pit_
<< " anchor ypos = " << d->anchor_ypos_);
+
+ // Remember what has just been done for the next draw() step
+ if (paint_caret)
+ d->caret_slice_ = bottomSlice;
+ else
+ d->caret_slice_ = CursorSlice();
}
class ParIterator;
class ParagraphMetrics;
class Point;
+class Row;
class TexRow;
class Text;
class TextMetrics;
/// 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;
void cursorPosAndHeight(Point & p, int & h) const;
///
- void draw(frontend::Painter & pain);
+ void draw(frontend::Painter & pain, bool paint_caret);
/// get this view's keyboard map handler.
Intl & getIntl();
// Row signature; has row changed since last paint?
row.setCrc(pm.computeRowSignature(row, *bv_));
bool row_has_changed = row.changed()
- || bv_->hadHorizScrollOffset(text_, pit, row.pos());
+ || bv_->hadHorizScrollOffset(text_, pit, row.pos())
+ || bv_->needRepaint(text_, row);
// Take this opportunity to spellcheck the row contents.
if (row_has_changed && pi.do_spellcheck && lyxrc.spellcheck_continuously) {