[vte/wip/egmont/bidi] fine grained gtk invalidate, part 1
- From: Egmont Koblinger <egmontkob src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vte/wip/egmont/bidi] fine grained gtk invalidate, part 1
- Date: Wed, 29 May 2019 12:34:53 +0000 (UTC)
commit d8047badacef0bf951f7b8663023bcbedb5e4b15
Author: Egmont Koblinger <egmont gmail com>
Date: Wed May 29 14:34:34 2019 +0200
fine grained gtk invalidate, part 1
src/vte.cc | 127 +++++++++++++++++++++++++++++++++++++----------------
src/vteinternal.hh | 6 ++-
src/vteseq.cc | 26 +++++------
3 files changed, 106 insertions(+), 53 deletions(-)
---
diff --git a/src/vte.cc b/src/vte.cc
index 5591f664..fa9e9396 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -245,10 +245,22 @@ Terminal::cursor_might_be_displayed() const
}
/* Note that end_row is inclusive. This is not as nice as end-exclusive,
- * but saves us from a +1 almost everywhere where this method is called. */
+ * but saves us from a +1 almost everywhere where this method is called.
+ *
+ * If @extend, the region is extended in both directions up to an explicit
+ * newline (or a safety limit) to invalidate entire paragraphs of text.
+ * This is to be used whenever the underlying data changes, because any such
+ * change might alter the desired BiDi, syntax highlighting etc. of all other
+ * rows of the involved paragraph(s).
+ *
+ * If not @extend, only the requested rows are invalidated. This is to be
+ * used when only the desired rendering changes but not the underlying data,
+ * e.g. moving or blinking cursor, highligthing with the mouse etc.
+ */
void
Terminal::invalidate_rows(vte::grid::row_t row_start,
- vte::grid::row_t row_end /* inclusive */)
+ vte::grid::row_t row_end /* inclusive */,
+ bool extend)
{
if (G_UNLIKELY (!widget_realized()))
return;
@@ -260,24 +272,57 @@ Terminal::invalidate_rows(vte::grid::row_t row_start,
return;
_vte_debug_print (VTE_DEBUG_UPDATES,
- "Invalidating rows %ld..%ld.\n",
- row_start, row_end);
+ "Invalidating rows %ld..%ld (extend: %s).\n",
+ row_start, row_end, extend ? "true" : "false");
_vte_debug_print (VTE_DEBUG_WORK, "?");
- // HACK for BiDi: Always invalidate everything.
- // In fact we'd need to invalidate the entire implicit paragraph.
- if (TRUE) {
- invalidate_all();
- return;
- }
+ if (extend) {
+ /* Scrolled back by so much that changes to the writable area
+ * may not affect the current viewport's rendering. */
+ if (m_screen->insert_delta - VTE_RINGVIEW_PARAGRAPH_LENGTH_MAX > last_displayed_row())
+ return;
+ } else {
+ /* Scrolled back, visible parts didn't change. */
+ if (row_start > last_displayed_row())
+ return;
+ }
- /* Scrolled back, visible parts didn't change. */
- if (row_start > last_displayed_row())
- return;
+ if (extend) {
+ /* Extending the start is a bit tricky.
+ *
+ * First extend it (towards lower numbered indices), but only up to
+ * insert_delta, which is still guaranteed to be in the ring's memory. */
+ while (row_start > m_screen->insert_delta) {
+ if (!m_screen->row_data->is_soft_wrapped(row_start - 1))
+ break;
+ row_start--;
+ }
+
+ /* If we haven't seen a newline yet, stop walking backwards row by row.
+ * This is because we might need to access row_stream in order to check
+ * its wrapped state, a way too expensive operation while processing
+ * incoming data. Let displaying do extra work instead.
+ * So just invalidate everything to the top. */
+ if (row_start < m_screen->insert_delta) {
+ row_start = first_displayed_row();
+ }
+
+ /* Extending the end is simple. Just walk until we go offscreen or
+ * find an explicit newline. */
+ while (row_end < last_displayed_row()) {
+ if (!m_screen->row_data->is_soft_wrapped(row_end))
+ break;
+ row_end++;
+ }
+
+ _vte_debug_print (VTE_DEBUG_UPDATES,
+ "Invalidating rows extended to %ld..%ld.\n",
+ row_start, row_end);
+ }
- /* Scrollbar is at default position, all the writable rows changed. */
- if (row_start == first_displayed_row() &&
- row_end - row_start + 1 == m_row_count) {
+ /* Recognize if we're already invalidating everything. */
+ if (row_start <= first_displayed_row() &&
+ row_end >= last_displayed_row()) {
invalidate_all();
return;
}
@@ -319,19 +364,21 @@ Terminal::invalidate_rows(vte::grid::row_t row_start,
/* Convenience method */
void
-Terminal::invalidate_row(vte::grid::row_t row)
+Terminal::invalidate_row(vte::grid::row_t row, bool extend)
{
- invalidate_rows(row, row);
+ invalidate_rows(row, row, extend);
}
+/* This is only used by the selection code, so no need to extend the area. */
void
Terminal::invalidate(vte::grid::span const& s)
{
if (!s.empty())
- invalidate_rows(s.start_row(), s.last_row());
+ invalidate_rows(s.start_row(), s.last_row(), false);
}
-/* Invalidates the symmetrical difference ("XOR" area) of the two spans */
+/* Invalidates the symmetrical difference ("XOR" area) of the two spans.
+ * This is only used by the selection code, so no need to extend the area. */
void
Terminal::invalidate_symmetrical_difference(vte::grid::span const& a, vte::grid::span const& b, bool block)
{
@@ -345,15 +392,18 @@ Terminal::invalidate_symmetrical_difference(vte::grid::span const& a, vte::grid:
if (block) {
/* We could optimize when the columns don't change, probably not worth it. */
invalidate_rows (std::min (a.start_row(), b.start_row()),
- std::max (a.last_row(), b.last_row()));
+ std::max (a.last_row(), b.last_row()),
+ false);
} else {
if (a.start() != b.start()) {
invalidate_rows (std::min (a.start_row(), b.start_row()),
- std::max (a.start_row(), b.start_row()));
+ std::max (a.start_row(), b.start_row()),
+ false);
}
if (a.end() != b.end()) {
invalidate_rows (std::min (a.last_row(), b.last_row()),
- std::max (a.last_row(), b.last_row()));
+ std::max (a.last_row(), b.last_row()),
+ false);
}
}
}
@@ -544,7 +594,7 @@ Terminal::invalidate_cursor_once(bool periodic)
_vte_debug_print(VTE_DEBUG_UPDATES,
"Invalidating cursor in row %ld.\n",
row);
- invalidate_row(row);
+ invalidate_row(row, false);
}
}
@@ -2666,7 +2716,7 @@ Terminal::cleanup_fragments(long start,
cell_end->c = ' ';
cell_end->attr.set_fragment(false);
cell_end->attr.set_columns(1);
- invalidate_row(m_screen->cursor.row);
+ invalidate_row(m_screen->cursor.row, false);
}
}
@@ -2690,7 +2740,7 @@ Terminal::cleanup_fragments(long start,
"Cleaning CJK left half at %ld\n",
col);
g_assert(start - col == 1);
- invalidate_row(m_screen->cursor.row);
+ invalidate_row(m_screen->cursor.row, false);
}
keep_going = FALSE;
}
@@ -2729,7 +2779,7 @@ Terminal::cursor_down(bool explicit_sequence)
ring_insert(m_screen->cursor.row, false);
/* Force the areas below the region to be
* redrawn -- they've moved. */
- invalidate_rows(start, end);
+ invalidate_rows(start, end, true /* FIXME */);
/* Force scroll. */
adjust_adjustments();
} else {
@@ -2739,7 +2789,7 @@ Terminal::cursor_down(bool explicit_sequence)
ring_remove(start);
ring_insert(end, true);
/* Update the display. */
- invalidate_rows(start, end);
+ invalidate_rows(start, end, true /* FIXME */);
}
} else {
/* Scroll up with history. */
@@ -2976,7 +3026,7 @@ Terminal::insert_char(gunichar c,
/* Always invalidate since we put the mark on the *previous* cell
* and the higher level code doesn't know this. */
// FIXMEegmont could this be cleaned up now that we invalidate rows?
- invalidate_row(row_num);
+ invalidate_row(row_num, true);
goto done;
} else {
@@ -3021,7 +3071,7 @@ Terminal::insert_char(gunichar c,
/* Signal that this part of the window needs drawing. */
if (G_UNLIKELY (invalidate_now)) {
- invalidate_row(m_screen->cursor.row);
+ invalidate_row(m_screen->cursor.row, true);
}
m_screen->cursor.col = col;
@@ -3066,7 +3116,7 @@ Terminal::apply_bidi_attributes(vte::grid::row_t row, guint8 bidi_flags, guint8
rowdata->attr.bidi_flags &= ~bidi_flags_mask;
rowdata->attr.bidi_flags |= bidi_flags;
- invalidate_row(row);
+ invalidate_row(row, false /* ugly */);
if (!rowdata->attr.soft_wrapped)
return;
row++;
@@ -3747,7 +3797,7 @@ Terminal::process_incoming()
bbox_top = std::max(bbox_top, top_row);
bbox_bottom = std::min(bbox_bottom, bottom_row);
- invalidate_rows(bbox_top, bbox_bottom);
+ invalidate_rows(bbox_top, bbox_bottom, true);
bbox_bottom = -G_MAXINT;
bbox_top = G_MAXINT;
@@ -3809,7 +3859,7 @@ Terminal::process_incoming()
bbox_top = std::max(bbox_top, top_row);
bbox_bottom = std::min(bbox_bottom, bottom_row);
- invalidate_rows(bbox_top, bbox_bottom);
+ invalidate_rows(bbox_top, bbox_bottom, true);
invalidated_text = FALSE;
bbox_bottom = -G_MAXINT;
@@ -3876,21 +3926,21 @@ Terminal::process_incoming()
bbox_top = std::max(bbox_top, top_row);
bbox_bottom = std::min(bbox_bottom, bottom_row);
- invalidate_rows(bbox_top, bbox_bottom);
+ invalidate_rows(bbox_top, bbox_bottom, true);
}
if ((saved_cursor.col != m_screen->cursor.col) ||
(saved_cursor.row != m_screen->cursor.row)) {
/* invalidate the old and new cursor positions */
if (saved_cursor_visible)
- invalidate_row(saved_cursor.row);
+ invalidate_row(saved_cursor.row, false);
invalidate_cursor_once();
check_cursor_blink();
/* Signal that the cursor moved. */
queue_cursor_moved();
} else if ((saved_cursor_visible != m_modes_private.DEC_TEXT_CURSOR()) ||
(saved_cursor_style != m_cursor_style)) {
- invalidate_row(saved_cursor.row);
+ invalidate_row(saved_cursor.row, false);
check_cursor_blink();
}
@@ -5895,7 +5945,7 @@ Terminal::hyperlink_invalidate_and_get_bbox(vte::base::Ring::hyperlink_idx_t idx
}
}
if (G_UNLIKELY (do_invalidate_row)) {
- invalidate_row(row);
+ invalidate_row(row, false);
}
}
}
@@ -6020,6 +6070,7 @@ Terminal::match_hilite_clear()
}
}
+/* This is only used by the dingu matching code, so no need to extend the area. */
void
Terminal::invalidate_match_span()
{
@@ -10428,7 +10479,7 @@ Terminal::select_text(vte::grid::column_t start_col,
widget_copy(VTE_SELECTION_PRIMARY, VTE_FORMAT_TEXT);
emit_selection_changed();
- invalidate_rows(start_row, end_row);
+ invalidate_rows(start_row, end_row, false);
}
void
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index 84d3b482..4e2fe679 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -646,9 +646,11 @@ public:
bool insert,
bool invalidate_now);
- void invalidate_row(vte::grid::row_t row);
+ void invalidate_row(vte::grid::row_t row,
+ bool extend);
void invalidate_rows(vte::grid::row_t row_start,
- vte::grid::row_t row_end /* inclusive */);
+ vte::grid::row_t row_end /* inclusive */,
+ bool extend);
void invalidate(vte::grid::span const& s);
void invalidate_symmetrical_difference(vte::grid::span const& a, vte::grid::span const& b, bool
block);
void invalidate_match_span();
diff --git a/src/vteseq.cc b/src/vteseq.cc
index d5b18b23..094b4020 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -317,7 +317,7 @@ Terminal::clear_current_line()
rowdata->attr.soft_wrapped = 0;
rowdata->attr.bidi_flags = get_bidi_flags();
/* Repaint this row. */
- invalidate_row(m_screen->cursor.row);
+ invalidate_row(m_screen->cursor.row, false /* FIXME */);
}
/* We've modified the display. Make a note of it. */
@@ -332,7 +332,7 @@ Terminal::clear_above_current()
if (m_screen->insert_delta > _vte_ring_delta(m_screen->row_data)) {
auto rowdata = _vte_ring_index_writable(m_screen->row_data, m_screen->insert_delta - 1);
rowdata->attr.soft_wrapped = 0;
- invalidate_row(m_screen->insert_delta - 1); // FIXME
+ invalidate_row(m_screen->insert_delta - 1, false /* FIXME */); // FIXME
}
/* If the cursor is actually on the screen, clear data in the row
* which corresponds to the cursor. */
@@ -348,7 +348,7 @@ Terminal::clear_above_current()
rowdata->attr.soft_wrapped = 0;
rowdata->attr.bidi_flags = get_bidi_flags();
/* Repaint the row. */
- invalidate_row(i);
+ invalidate_row(i, false /* FIXME */);
}
}
/* We've modified the display. Make a note of it. */
@@ -384,7 +384,7 @@ Terminal::scroll_text(vte::grid::row_t scroll_amount)
}
/* Update the display. */
- invalidate_rows(start, end);
+ invalidate_rows(start, end, true /* FIXME */);
/* Adjust the scrollbars if necessary. */
adjust_adjustments();
@@ -707,7 +707,7 @@ Terminal::clear_to_bol()
}
}
/* Repaint this row. */
- invalidate_row(m_screen->cursor.row);
+ invalidate_row(m_screen->cursor.row, true);
/* We've modified the display. Make a note of it. */
m_text_deleted_flag = TRUE;
@@ -764,7 +764,7 @@ Terminal::clear_below_current()
if (i > m_screen->cursor.row)
rowdata->attr.bidi_flags = get_bidi_flags();
/* Repaint this row. */
- invalidate_row(i);
+ invalidate_row(i, true /* FIXME */);
}
/* We've modified the display. Make a note of it. */
@@ -803,7 +803,7 @@ Terminal::clear_to_eol()
}
rowdata->attr.soft_wrapped = 0;
/* Repaint this row. */
- invalidate_row(m_screen->cursor.row);
+ invalidate_row(m_screen->cursor.row, true /* FIXME */);
}
/*
@@ -935,7 +935,7 @@ Terminal::delete_character()
}
rowdata->attr.soft_wrapped = 0;
/* Repaint this row. */
- invalidate_row(m_screen->cursor.row);
+ invalidate_row(m_screen->cursor.row, true /* FIXME */);
}
}
@@ -993,7 +993,7 @@ Terminal::erase_characters(long count)
}
}
/* Repaint this row. */
- invalidate_row(m_screen->cursor.row);
+ invalidate_row(m_screen->cursor.row, true);
}
/* We've modified the display. Make a note of it. */
@@ -1108,7 +1108,7 @@ Terminal::move_cursor_tab_forward(int count)
}
}
- invalidate_row(m_screen->cursor.row);
+ invalidate_row(m_screen->cursor.row, false);
m_screen->cursor.col = newcol;
}
@@ -1324,7 +1324,7 @@ Terminal::insert_lines(vte::grid::row_t param)
}
m_screen->cursor.col = 0;
/* Update the display. */
- invalidate_rows(row, end);
+ invalidate_rows(row, end, true /* FIXME */);
/* Adjust the scrollbars if necessary. */
adjust_adjustments();
/* We've modified the display. Make a note of it. */
@@ -1359,7 +1359,7 @@ Terminal::delete_lines(vte::grid::row_t param)
}
m_screen->cursor.col = 0;
/* Update the display. */
- invalidate_rows(row, end);
+ invalidate_rows(row, end, true /* FIXME */);
/* Adjust the scrollbars if necessary. */
adjust_adjustments();
/* We've modified the display. Make a note of it. */
@@ -6753,7 +6753,7 @@ Terminal::RI(vte::parser::Sequence const& seq)
ring_remove(end);
ring_insert(start, true);
/* Update the display. */
- invalidate_rows(start, end);
+ invalidate_rows(start, end, true /* FIXME */);
} else {
/* Otherwise, just move the cursor up. */
m_screen->cursor.row--;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]