diff options
author | Egmont Koblinger <egmont@gmail.com> | 2019-06-30 15:29:07 +0200 |
---|---|---|
committer | Egmont Koblinger <egmont@gmail.com> | 2019-06-30 15:29:07 +0200 |
commit | 59017da98ce05dd4673d915ee4978aee7c155caa (patch) | |
tree | 285c55773d8bf35003e23a807240a75f3cd6d732 | |
parent | 3c6505bef69b6e4ee9e92cc8e9b6058109364ba5 (diff) | |
download | vte-59017da98ce05dd4673d915ee4978aee7c155caa.tar.gz |
ringview: Add RingView infrastructure
The RingView extracts the contents of the currently visible area plus
context lines up to the next hard newline (or a safety limit).
This can be used to perform display related tweaks, such as BiDi.
https://gitlab.gnome.org/GNOME/vte/issues/53
-rw-r--r-- | src/debug.cc | 1 | ||||
-rw-r--r-- | src/debug.h | 3 | ||||
-rw-r--r-- | src/meson.build | 2 | ||||
-rw-r--r-- | src/ringview.cc | 237 | ||||
-rw-r--r-- | src/ringview.hh | 97 | ||||
-rw-r--r-- | src/vte.cc | 87 | ||||
-rw-r--r-- | src/vteinternal.hh | 7 | ||||
-rw-r--r-- | src/vterowdata.cc | 8 | ||||
-rw-r--r-- | src/vterowdata.hh | 1 | ||||
-rw-r--r-- | src/widget.cc | 2 |
10 files changed, 443 insertions, 2 deletions
diff --git a/src/debug.cc b/src/debug.cc index afbd7413..e8dd8d08 100644 --- a/src/debug.cc +++ b/src/debug.cc @@ -57,6 +57,7 @@ _vte_debug_init(void) { "hyperlink", VTE_DEBUG_HYPERLINK }, { "modes", VTE_DEBUG_MODES }, { "emulation", VTE_DEBUG_EMULATION }, + { "ringview", VTE_DEBUG_RINGVIEW }, { "bidi", VTE_DEBUG_BIDI }, }; diff --git a/src/debug.h b/src/debug.h index 92d9d0f9..8601dad0 100644 --- a/src/debug.h +++ b/src/debug.h @@ -64,7 +64,8 @@ typedef enum { VTE_DEBUG_HYPERLINK = 1 << 24, VTE_DEBUG_MODES = 1 << 25, VTE_DEBUG_EMULATION = 1 << 26, - VTE_DEBUG_BIDI = 1 << 27, + VTE_DEBUG_RINGVIEW = 1 << 27, + VTE_DEBUG_BIDI = 1 << 28, } VteDebugFlags; void _vte_debug_init(void); diff --git a/src/meson.build b/src/meson.build index 29046b77..6b97aaec 100644 --- a/src/meson.build +++ b/src/meson.build @@ -70,6 +70,8 @@ libvte_common_sources = debug_sources + modes_sources + parser_sources + utf8_so 'refptr.hh', 'ring.cc', 'ring.hh', + 'ringview.cc', + 'ringview.hh', 'utf8.cc', 'utf8.hh', 'vte.cc', diff --git a/src/ringview.cc b/src/ringview.cc new file mode 100644 index 00000000..9e25bcbc --- /dev/null +++ b/src/ringview.cc @@ -0,0 +1,237 @@ +/* + * Copyright © 2018–2019 Egmont Koblinger + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <config.h> + +#include "debug.h" +#include "vtedefines.hh" +#include "vteinternal.hh" + +using namespace vte::base; + +RingView::RingView() +{ +} + +RingView::~RingView() +{ + pause(); +} + +/* Pausing a RingView frees up pretty much all of its memory. + * + * This is to be used when the terminal is unlikely to be painted or interacted with + * in the near future, e.g. the widget is unmapped. Not to be called too frequently, + * in order to avoid memory fragmentation. + * + * The RingView is resumed automatically on demand. + */ +void +RingView::pause() +{ + int i; + + if (m_paused) + return; + + _vte_debug_print (VTE_DEBUG_RINGVIEW, "Ringview: pause, freeing %d rows.\n", + m_rows_alloc_len); + + for (i = 0; i < m_rows_alloc_len; i++) { + _vte_row_data_fini(m_rows[i]); + g_free (m_rows[i]); + } + g_free (m_rows); + m_rows_alloc_len = 0; + + m_invalid = true; + m_paused = true; +} + +/* Allocate (again) the required memory. */ +void +RingView::resume() +{ + g_assert_cmpint (m_len, >=, 1); + + /* +16: A bit of arbitrary heuristics to likely prevent a quickly following + * realloc for the required context lines. */ + m_rows_alloc_len = m_len + 16; + m_rows = (VteRowData **) g_malloc (sizeof (VteRowData *) * m_rows_alloc_len); + for (int i = 0; i < m_rows_alloc_len; i++) { + m_rows[i] = (VteRowData *) g_malloc (sizeof (VteRowData)); + _vte_row_data_init (m_rows[i]); + } + + _vte_debug_print (VTE_DEBUG_RINGVIEW, "Ringview: resume, allocating %d rows\n", + m_rows_alloc_len); + + m_paused = false; +} + +void +RingView::set_ring(Ring *ring) +{ + if (G_LIKELY (ring == m_ring)) + return; + + m_ring = ring; + m_invalid = true; +} + +void +RingView::set_width(vte::grid::column_t width) +{ + if (G_LIKELY (width == m_width)) + return; + + m_width = width; + m_invalid = true; +} + +void +RingView::set_rows(vte::grid::row_t start, vte::grid::row_t len) +{ + /* Force at least 1 row, see bug 134. */ + len = MAX(len, 1); + + if (start == m_start && len == m_len) + return; + + /* With per-pixel scrolling, the desired viewport often shrinks by + * one row at one end, and remains the same at the other end. + * Save work by just keeping the current valid data in this case. */ + if (!m_invalid && start >= m_start && start + len <= m_start + m_len) + return; + + /* m_rows is expanded on demand in update() */ + + m_start = start; + m_len = len; + m_invalid = true; +} + +VteRowData const* +RingView::get_row(vte::grid::row_t row) const +{ + g_assert_cmpint(row, >=, m_top); + g_assert_cmpint(row, <, m_top + m_rows_len); + + return m_rows[row - m_top]; +} + +void +RingView::update() +{ + if (!m_invalid) + return; + if (m_paused) + resume(); + + /* Find the beginning of the topmost paragraph. + * + * Extract at most VTE_RINGVIEW_PARAGRAPH_LENGTH_MAX context rows. + * If this safety limit is reached then together with the first + * non-context row this paragraph fragment is already longer + * than VTE_RINGVIEW_PARAGRAPH_LENGTH_MAX lines, and thus the + * BiDi code will skip it. */ + vte::grid::row_t row = m_start; + const VteRowData *row_data; + + _vte_debug_print (VTE_DEBUG_RINGVIEW, "Ringview: updating for [%ld..%ld] (%ld rows).\n", + m_start, m_start + m_len - 1, m_len); + + int i = VTE_RINGVIEW_PARAGRAPH_LENGTH_MAX; + while (i--) { + if (!m_ring->is_soft_wrapped(row - 1)) + break; + row--; + } + + /* Extract the data beginning at the found row. + * + * Extract at most VTE_RINGVIEW_PARAGRAPH_LENGTH_MAX rows + * beyond the end of the specified area. Again, if this safety + * limit is reached then together with the last non-context row + * this paragraph fragment is already longer than + * VTE_RINGVIEW_PARAGRAPH_LENGTH_MAX lines, and thus the + * BiDi code will skip it. */ + m_top = row; + m_rows_len = 0; + while (row < m_start + m_len + VTE_RINGVIEW_PARAGRAPH_LENGTH_MAX) { + if (G_UNLIKELY (m_rows_len == m_rows_alloc_len)) { + /* Don't realloc too aggressively. */ + m_rows_alloc_len = std::max(m_rows_alloc_len + 1, m_rows_alloc_len * 5 / 4 /* whatever */); + _vte_debug_print (VTE_DEBUG_RINGVIEW, "Ringview: reallocate to %d rows\n", + m_rows_alloc_len); + m_rows = (VteRowData **) g_realloc (m_rows, sizeof (VteRowData *) * m_rows_alloc_len); + for (int j = m_rows_len; j < m_rows_alloc_len; j++) { + m_rows[j] = (VteRowData *) g_malloc (sizeof (VteRowData)); + _vte_row_data_init (m_rows[j]); + } + } + + row_data = _vte_ring_contains(m_ring, row) ? m_ring->index(row) : nullptr; + if (G_LIKELY (row_data != nullptr)) { + _vte_row_data_copy (row_data, m_rows[m_rows_len]); + /* Make sure that the extracted data is not wider than the screen, + * something that can happen if the window was narrowed with rewrapping disabled. + * Also make sure that we won't end up with unfinished characters. + * FIXME remove this once bug 135 is addressed. */ + if (G_UNLIKELY (_vte_row_data_length(m_rows[m_rows_len]) > m_width)) { + int j = m_width; + while (j > 0) { + VteCell const* cell = _vte_row_data_get(m_rows[m_rows_len], j); + if (!cell->attr.fragment()) + break; + j--; + } + _vte_row_data_shrink(m_rows[m_rows_len], j); + } + } else { + _vte_row_data_clear (m_rows[m_rows_len]); + } + m_rows_len++; + row++; + + /* Once the bottom of the specified area is reached, stop at a hard newline. */ + if (row >= m_start + m_len && (!row_data || !row_data->attr.soft_wrapped)) + break; + } + + _vte_debug_print (VTE_DEBUG_RINGVIEW, "Ringview: extracted %ld+%ld context lines: [%ld..%ld] (%d rows).\n", + m_start - m_top, (m_top + m_rows_len) - (m_start + m_len), + m_top, m_top + m_rows_len - 1, m_rows_len); + + /* Loop through paragraphs of the extracted text, and do whatever we need to do on each paragraph. */ + auto top = m_top; + row = top; + while (row < m_top + m_rows_len) { + row_data = m_rows[row - m_top]; + if (!row_data->attr.soft_wrapped || row == m_top + m_rows_len - 1) { + /* Found a paragraph from @top to @row, inclusive. */ + + /* Doing BiDi, syntax highlighting etc. come here in the future. */ + + top = row + 1; + } + row++; + } + + m_invalid = false; +} diff --git a/src/ringview.hh b/src/ringview.hh new file mode 100644 index 00000000..32b12878 --- /dev/null +++ b/src/ringview.hh @@ -0,0 +1,97 @@ +/* + * Copyright © 2018–2019 Egmont Koblinger + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include <glib.h> + +#include "ring.hh" +#include "vterowdata.hh" +#include "vtetypes.hh" +#include "vteunistr.h" + +namespace vte { + +namespace base { + +/* + * RingView provides a "view" to a continuous segment of the Ring (or stream), + * typically the user visible area. + * + * It computes additional data that are needed to display the contents (or handle + * user events such as mouse click), but not needed for the terminal emulation logic. + * In order to save tons of resources, these data are computed when the Ring's + * contents are about to be displayed, rather than whenever they change. + * + * For computing these data, context lines (outside of the specified region of the + * Ring) are also taken into account up to the next hard newline or a safety limit. + * + * Currently RingView is used for BiDi: to figure out which logical character is + * mapped to which visual position. + * + * Future possible uses include "highlight all" for the search match, and + * syntax highlighting. URL autodetection might also be ported to this + * infrastructure one day. + */ +class RingView { +public: + RingView(); + ~RingView(); + + // prevent accidents + RingView(RingView& o) = delete; + RingView(RingView const& o) = delete; + RingView(RingView&& o) = delete; + RingView& operator= (RingView& o) = delete; + RingView& operator= (RingView const& o) = delete; + RingView& operator= (RingView&& o) = delete; + + void set_ring(Ring *ring); + void set_rows(vte::grid::row_t start, vte::grid::row_t len); + void set_width(vte::grid::column_t width); + inline constexpr vte::grid::column_t get_width() const noexcept { return m_width; } + + inline void invalidate() { m_invalid = true; } + inline constexpr bool is_updated() const noexcept { return !m_invalid; } + void update(); + void pause(); + + VteRowData const* get_row(vte::grid::row_t row) const; + +private: + Ring *m_ring{nullptr}; + + VteRowData **m_rows{nullptr}; + int m_rows_len{0}; + int m_rows_alloc_len{0}; + + vte::grid::row_t m_top{0}; /* the row of the Ring corresponding to m_rows[0] */ + + vte::grid::row_t m_start{0}; + vte::grid::row_t m_len{0}; + vte::grid::column_t m_width{0}; + + bool m_invalid{true}; + bool m_paused{true}; + + void resume(); +}; + +}; /* namespace base */ + +}; /* namespace vte */ @@ -41,6 +41,7 @@ #include "vtedraw.hh" #include "reaper.hh" #include "ring.hh" +#include "ringview.hh" #include "caps.hh" #include "widget.hh" @@ -561,6 +562,7 @@ Terminal::set_hard_wrapped(vte::grid::row_t row) row_data->attr.soft_wrapped = false; + m_ringview.invalidate(); invalidate_rows_and_context(row, row + 1); } @@ -595,6 +597,7 @@ Terminal::set_soft_wrapped(vte::grid::row_t row) } while (row_data != nullptr); } + m_ringview.invalidate(); invalidate_rows_and_context(row, row + 1); } @@ -1628,6 +1631,9 @@ Terminal::confined_grid_coords_from_event(GdkEvent const* event) const vte::grid::coords Terminal::grid_coords_from_view_coords(vte::view::coords const& pos) const { + /* Our caller had to update the ringview (we can't do because we're const). */ + g_assert(m_ringview.is_updated()); + vte::grid::column_t col; if (pos.x >= 0 && pos.x < m_view_usable_extents.width()) col = pos.x / m_cell_width; @@ -1715,6 +1721,9 @@ Terminal::confine_grid_coords(vte::grid::coords const& rowcol) const vte::grid::halfcoords Terminal::selection_grid_halfcoords_from_view_coords(vte::view::coords const& pos) const { + /* Our caller had to update the ringview (we can't do because we're const). */ + g_assert(m_ringview.is_updated()); + vte::grid::row_t row = pixel_to_row(pos.y); vte::grid::halfcolumn_t halfcolumn; @@ -1746,6 +1755,9 @@ Terminal::selection_maybe_swap_endpoints(vte::view::coords const& pos) if (m_selection_resolved.empty()) return; + /* Need to ensure the ringview is updated. */ + ringview_update(); + auto current = selection_grid_halfcoords_from_view_coords (pos); if (m_selection_block_mode) { @@ -1797,7 +1809,13 @@ Terminal::hyperlink_check(GdkEvent *event) const char *hyperlink; const char *separator; - if (!m_allow_hyperlink || !rowcol_from_event(event, &col, &row)) + if (!m_allow_hyperlink) + return NULL; + + /* Need to ensure the ringview is updated. */ + ringview_update(); + + if (!rowcol_from_event(event, &col, &row)) return NULL; _vte_ring_get_hyperlink_at_position(m_screen->row_data, row, col, false, &hyperlink); @@ -1821,6 +1839,10 @@ Terminal::regex_match_check(GdkEvent *event, int *tag) { long col, row; + + /* Need to ensure the ringview is updated. */ + ringview_update(); + if (!rowcol_from_event(event, &col, &row)) return FALSE; @@ -1847,6 +1869,9 @@ Terminal::regex_match_check_extra(GdkEvent *event, g_assert(regexes != nullptr || n_regexes == 0); g_assert(matches != nullptr); + /* Need to ensure the ringview is updated. */ + ringview_update(); + if (!rowcol_from_event(event, &col, &row)) return false; @@ -3175,6 +3200,7 @@ Terminal::apply_bidi_attributes(vte::grid::row_t start, guint8 bidi_flags, guint _vte_debug_print(VTE_DEBUG_BIDI, "Applied BiDi parameters to rows %ld..%ld.\n", start, row); + m_ringview.invalidate(); invalidate_rows(start, row); } @@ -3948,6 +3974,7 @@ Terminal::process_incoming() } if (modified || (m_screen != previous_screen)) { + m_ringview.invalidate(); /* Signal that the visible contents changed. */ queue_contents_changed(); } @@ -5593,6 +5620,9 @@ Terminal::modify_selection (vte::view::coords const& pos) { g_assert (m_selecting); + /* Need to ensure the ringview is updated. */ + ringview_update(); + auto current = selection_grid_halfcoords_from_view_coords (pos); if (current == m_selection_last) @@ -5611,6 +5641,9 @@ bool Terminal::cell_is_selected(vte::grid::column_t col, vte::grid::row_t row) const { + /* Our caller had to update the ringview (we can't do because we're const). */ + g_assert(m_ringview.is_updated()); + if (m_selection_block_mode) { /* In block mode, make sure CJKs and TABs aren't cut in half. */ while (col > 0) { @@ -5856,6 +5889,9 @@ bool Terminal::maybe_send_mouse_drag(vte::grid::coords const& unconfined_rowcol, GdkEventType event_type) { + /* Need to ensure the ringview is updated. */ + ringview_update(); + auto rowcol = confine_grid_coords(unconfined_rowcol); /* First determine if we even want to send notification. */ @@ -5975,6 +6011,9 @@ Terminal::hyperlink_hilite_update() _vte_debug_print (VTE_DEBUG_HYPERLINK, "hyperlink_hilite_update\n"); + /* Need to ensure the ringview is updated. */ + ringview_update(); + /* m_mouse_last_position contains the current position, see bug 789536 comment 24. */ auto pos = m_mouse_last_position; @@ -6076,6 +6115,9 @@ Terminal::invalidate_match_span() void Terminal::match_hilite_update() { + /* Need to ensure the ringview is updated. */ + ringview_update(); + /* m_mouse_last_position contains the current position, see bug 789536 comment 24. */ auto pos = m_mouse_last_position; @@ -6826,6 +6868,9 @@ Terminal::start_selection (vte::view::coords const& pos, if (m_selection_block_mode) type = selection_type_char; + /* Need to ensure the ringview is updated. */ + ringview_update(); + m_selection_origin = m_selection_last = selection_grid_halfcoords_from_view_coords(pos); /* Record the selection type. */ @@ -6987,6 +7032,9 @@ Terminal::widget_motion_notify(GdkEventMotion *event) { bool handled = false; + /* Need to ensure the ringview is updated. */ + ringview_update(); + GdkEvent* base_event = reinterpret_cast<GdkEvent*>(event); auto pos = view_coords_from_event(base_event); auto rowcol = grid_coords_from_view_coords(pos); @@ -7052,6 +7100,9 @@ Terminal::widget_button_press(GdkEventButton *event) bool handled = false; gboolean start_selecting = FALSE, extend_selecting = FALSE; + /* Need to ensure the ringview is updated. */ + ringview_update(); + GdkEvent* base_event = reinterpret_cast<GdkEvent*>(event); auto pos = view_coords_from_event(base_event); auto rowcol = grid_coords_from_view_coords(pos); @@ -7201,6 +7252,9 @@ Terminal::widget_button_release(GdkEventButton *event) { bool handled = false; + /* Need to ensure the ringview is updated. */ + ringview_update(); + GdkEvent* base_event = reinterpret_cast<GdkEvent*>(event); auto pos = view_coords_from_event(base_event); auto rowcol = grid_coords_from_view_coords(pos); @@ -8215,6 +8269,12 @@ Terminal::widget_size_allocate(GtkAllocation *allocation) } void +Terminal::widget_unmap() +{ + m_ringview.pause(); +} + +void Terminal::widget_unrealize() { /* Deallocate the cursors. */ @@ -9006,6 +9066,19 @@ Terminal::draw_cells_with_attributes(struct _vte_draw_text_request *items, g_free(cells); } +void +Terminal::ringview_update() +{ + auto first_row = first_displayed_row(); + auto last_row = last_displayed_row(); + if (cursor_is_onscreen()) + last_row = std::max(last_row, m_screen->cursor.row); + + m_ringview.set_ring (m_screen->row_data); + m_ringview.set_rows (first_row, last_row - first_row + 1); + m_ringview.set_width (m_column_count); + m_ringview.update (); +} /* Paint the contents of a given row at the given location. Take advantage * of multiple-draw APIs by finding runs of characters with identical @@ -9034,6 +9107,9 @@ Terminal::draw_rows(VteScreen *screen_, auto const column_count = m_column_count; uint32_t const attr_mask = m_allow_bold ? ~0 : ~VTE_ATTR_BOLD_MASK; + /* Need to ensure the ringview is updated. */ + ringview_update(); + items = g_newa (struct _vte_draw_text_request, column_count); /* Paint the background. @@ -9259,6 +9335,9 @@ Terminal::paint_cursor() if (CLAMP(col, 0, m_column_count - 1) != col) return; + /* Need to ensure the ringview is updated. */ + ringview_update(); + /* Find the first cell of the character "under" the cursor. * This is for CJK. For TAB, paint the cursor where it really is. */ auto cell = find_charcell(col, drow); @@ -9390,6 +9469,9 @@ Terminal::paint_im_preedit_string() if (m_im_preedit.empty()) return; + /* Need to ensure the ringview is updated. */ + ringview_update(); + /* Keep local copies of rendering information. */ width = m_cell_width; height = m_cell_height; @@ -9609,6 +9691,9 @@ Terminal::widget_scroll(GdkEventScroll *event) gint cnt, i; int button; + /* Need to ensure the ringview is updated. */ + ringview_update(); + GdkEvent *base_event = reinterpret_cast<GdkEvent*>(event); auto rowcol = confined_grid_coords_from_event(base_event); diff --git a/src/vteinternal.hh b/src/vteinternal.hh index a5d33abe..28c65d1f 100644 --- a/src/vteinternal.hh +++ b/src/vteinternal.hh @@ -25,6 +25,7 @@ #include "vtedraw.hh" #include "reaper.hh" #include "ring.hh" +#include "ringview.hh" #include "buffer.h" #include "parser.hh" #include "parser-glue.hh" @@ -612,6 +613,9 @@ public: const char *m_hyperlink_hover_uri; /* data is owned by the ring */ long m_hyperlink_auto_id; + /* RingView and friends */ + vte::base::RingView m_ringview; + /* BiDi parameters outside of ECMA and DEC private modes */ guint m_bidi_rtl : 1; @@ -749,6 +753,7 @@ public: void widget_constructed(); void widget_realize(); void widget_unrealize(); + void widget_unmap(); void widget_style_updated(); void widget_focus_in(GdkEventFocus *event); void widget_focus_out(GdkEventFocus *event); @@ -1327,6 +1332,8 @@ public: vte::parser::StringTokeniser::const_iterator& token, vte::parser::StringTokeniser::const_iterator const& endtoken) noexcept; + void ringview_update(); + /* Sequence handlers */ bool m_line_wrapped; // signals line wrapped from character insertion // Note: inlining the handlers seems to worsen the performance, so we don't do that diff --git a/src/vterowdata.cc b/src/vterowdata.cc index 88edba1a..7f9f6b40 100644 --- a/src/vterowdata.cc +++ b/src/vterowdata.cc @@ -172,6 +172,14 @@ void _vte_row_data_shrink (VteRowData *row, gulong max_len) row->len = max_len; } +void _vte_row_data_copy (const VteRowData *src, VteRowData *dst) +{ + _vte_row_data_ensure (dst, src->len); + dst->len = src->len; + dst->attr = src->attr; + memcpy(dst->cells, src->cells, src->len * sizeof (src->cells[0])); +} + /* Get the length, ignoring trailing empty cells (with a custom background color). */ guint16 _vte_row_data_nonempty_length (const VteRowData *row) { diff --git a/src/vterowdata.hh b/src/vterowdata.hh index 12cbf311..10b76b6a 100644 --- a/src/vterowdata.hh +++ b/src/vterowdata.hh @@ -80,6 +80,7 @@ void _vte_row_data_append (VteRowData *row, const VteCell *cell); void _vte_row_data_remove (VteRowData *row, gulong col); void _vte_row_data_fill (VteRowData *row, const VteCell *cell, gulong len); void _vte_row_data_shrink (VteRowData *row, gulong max_len); +void _vte_row_data_copy (const VteRowData *src, VteRowData *dst); guint16 _vte_row_data_nonempty_length (const VteRowData *row); G_END_DECLS diff --git a/src/widget.cc b/src/widget.cc index 331ddba9..5af5d47c 100644 --- a/src/widget.cc +++ b/src/widget.cc @@ -334,6 +334,8 @@ Widget::size_allocate(GtkAllocation* allocation) noexcept void Widget::unmap() noexcept { + m_terminal->widget_unmap(); + if (m_event_window) gdk_window_hide(m_event_window); } |