From 9c0c6b8fd5a7ea8b819798add9f0605da749062b Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Wed, 23 Aug 2023 14:09:47 +1000 Subject: [PATCH] Revert "Only make cursor visible after buffer or selection change" This is currently broken on various corner cases and breaks the "master branch should be good for day to day work" implicit rule, ongoing work to stabilize this feature will take place on the no-cursor-move-on-scroll branch until its deemed ready. This reverts commit 1e38045d702ec6eb2425016d9b02636270ab1b1e. Closes #4963 --- src/context.hh | 24 ++------ src/highlighter.hh | 1 - src/highlighters.cc | 6 +- src/input_handler.cc | 36 ++++++------ src/normal.cc | 2 +- src/window.cc | 57 +++++++++---------- src/window.hh | 6 +- test/regression/3219-scroll-json-ui/script | 4 +- .../regression/4839-scroll-invalid-cursor/cmd | 2 +- .../4839-scroll-invalid-cursor/script | 4 +- 10 files changed, 58 insertions(+), 84 deletions(-) diff --git a/src/context.hh b/src/context.hh index 119e4495..69377148 100644 --- a/src/context.hh +++ b/src/context.hh @@ -144,7 +144,6 @@ public: void repeat_last_select() { if (m_last_select) m_last_select(*this); } Buffer* last_buffer() const; - private: void begin_edition(); void end_edition(); @@ -216,16 +215,9 @@ struct ScopedEdition ScopedEdition(Context& context) : m_context{context}, m_buffer{context.has_buffer() ? &context.buffer() : nullptr} - { - if (m_buffer) - m_context.begin_edition(); - } + { if (m_buffer) m_context.begin_edition(); } - ~ScopedEdition() - { - if (m_buffer) - m_context.end_edition(); - } + ~ScopedEdition() { if (m_buffer) m_context.end_edition(); } Context& context() const { return m_context; } private: @@ -238,19 +230,11 @@ struct ScopedSelectionEdition ScopedSelectionEdition(Context& context) : m_context{context}, m_buffer{not (m_context.flags() & Context::Flags::Draft) and context.has_buffer() ? &context.buffer() : nullptr} - { - if (m_buffer) - m_context.m_selection_history.begin_edition(); - } - + { if (m_buffer) m_context.m_selection_history.begin_edition(); } ScopedSelectionEdition(ScopedSelectionEdition&& other) : m_context{other.m_context}, m_buffer{other.m_buffer} { other.m_buffer = nullptr; } - ~ScopedSelectionEdition() - { - if (m_buffer) - m_context.m_selection_history.end_edition(); - } + ~ScopedSelectionEdition() { if (m_buffer) m_context.m_selection_history.end_edition(); } private: Context& m_context; SafePtr m_buffer; diff --git a/src/highlighter.hh b/src/highlighter.hh index 925dcaa7..ad94f44d 100644 --- a/src/highlighter.hh +++ b/src/highlighter.hh @@ -46,7 +46,6 @@ struct DisplaySetup DisplayCoord cursor_pos; // Offset of line and columns that must remain visible around cursor DisplayCoord scroll_offset; - bool ensure_cursor_visible; }; using HighlighterIdList = ConstArrayView; diff --git a/src/highlighters.cc b/src/highlighters.cc index 156b4b2c..65f801cb 100644 --- a/src/highlighters.cc +++ b/src/highlighters.cc @@ -752,8 +752,7 @@ struct WrapHighlighter : Highlighter win_line += wrap_count + 1; // scroll window to keep cursor visible, and update range as lines gets removed - while (setup.ensure_cursor_visible and - buf_line >= cursor.line and setup.first_line < cursor.line and + while (buf_line >= cursor.line and setup.first_line < cursor.line and setup.cursor_pos.line + setup.scroll_offset.line >= win_height) { auto remove_count = 1 + line_wrap_count(setup.first_line, indent); @@ -1661,8 +1660,7 @@ private: setup.cursor_pos.column += cursor_move; } - if (setup.ensure_cursor_visible and - last.line >= setup.first_line and + if (last.line >= setup.first_line and range.first.line <= setup.first_line + setup.line_count and range.first.line != last.line) { diff --git a/src/input_handler.cc b/src/input_handler.cc index ef45e149..66d30391 100644 --- a/src/input_handler.cc +++ b/src/input_handler.cc @@ -1870,27 +1870,25 @@ void scroll_window(Context& context, LineCount offset, bool mouse_dragging) win_pos.line = clamp(win_pos.line + offset, 0_line, line_count-1); + ScopedSelectionEdition selection_edition{context}; + SelectionList& selections = context.selections(); + Selection& main_selection = selections.main(); + const BufferCoord anchor = main_selection.anchor(); + const BufferCoordAndTarget cursor = main_selection.cursor(); + + auto cursor_off = mouse_dragging ? win_pos.line - window.position().line : 0; + + auto line = clamp(cursor.line + cursor_off, win_pos.line + scrolloff.line, + win_pos.line + win_dim.line - 1 - scrolloff.line); + + const ColumnCount tabstop = context.options()["tabstop"].get(); + auto new_cursor = buffer.offset_coord(cursor, line - cursor.line, tabstop); + BufferCoord new_anchor = (mouse_dragging or new_cursor == cursor) ? anchor : new_cursor; + window.set_position(win_pos); - if (mouse_dragging) - { - ScopedSelectionEdition selection_edition{context}; - SelectionList& selections = context.selections(); - Selection& main_selection = selections.main(); - const BufferCoord anchor = main_selection.anchor(); - const BufferCoordAndTarget cursor = main_selection.cursor(); + main_selection = { new_anchor, new_cursor }; - auto cursor_off = win_pos.line - window.position().line; - - auto line = clamp(cursor.line + cursor_off, win_pos.line + scrolloff.line, - win_pos.line + win_dim.line - 1 - scrolloff.line); - - const ColumnCount tabstop = context.options()["tabstop"].get(); - auto new_cursor = buffer.offset_coord(cursor, line - cursor.line, tabstop); - - main_selection = { anchor, new_cursor }; - - selections.sort_and_merge_overlapping(); - } + selections.sort_and_merge_overlapping(); } } diff --git a/src/normal.cc b/src/normal.cc index 8b26b1ff..b16b9c37 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -848,7 +848,7 @@ void regex_prompt(Context& context, String prompt, char reg, T func) { selections.update(); context.selections_write_only() = selections; - if (context.has_window() and event != PromptEvent::Validate) + if (context.has_window()) context.window().set_position(position); context.input_handler().set_prompt_face(context.faces()["Prompt"]); diff --git a/src/window.cc b/src/window.cc index b5d1db40..2a0469cf 100644 --- a/src/window.cc +++ b/src/window.cc @@ -85,34 +85,37 @@ static uint32_t compute_faces_hash(const FaceRegistry& faces) Window::Setup Window::build_setup(const Context& context) const { - return {m_position, m_dimensions, - context.buffer().timestamp(), - compute_faces_hash(context.faces()), - context.selections().main_index(), - context.selections() | gather>()}; + Vector selections; + for (auto& sel : context.selections()) + selections.push_back({sel.cursor(), sel.anchor()}); + + return { m_position, m_dimensions, + context.buffer().timestamp(), + compute_faces_hash(context.faces()), + context.selections().main_index(), + std::move(selections) }; } bool Window::needs_redraw(const Context& context) const { auto& selections = context.selections(); - return m_position != m_last_setup.position or + + if (m_position != m_last_setup.position or m_dimensions != m_last_setup.dimensions or context.buffer().timestamp() != m_last_setup.timestamp or selections.main_index() != m_last_setup.main_selection or selections.size() != m_last_setup.selections.size() or - compute_faces_hash(context.faces()) != m_last_setup.faces_hash or - not std::equal(selections.begin(), selections.end(), - m_last_setup.selections.begin(), m_last_setup.selections.end()); -} + compute_faces_hash(context.faces()) != m_last_setup.faces_hash) + return true; -bool Window::should_make_cursor_visible(const Context& context) const -{ - auto& selections = context.selections(); - return context.buffer().timestamp() != m_last_setup.timestamp or - selections.main_index() != m_last_setup.main_selection or - selections.size() != m_last_setup.selections.size() or - not std::equal(selections.begin(), selections.end(), - m_last_setup.selections.begin(), m_last_setup.selections.end()); + for (int i = 0; i < selections.size(); ++i) + { + if (selections[i].cursor() != m_last_setup.selections[i].begin or + selections[i].anchor() != m_last_setup.selections[i].end) + return true; + } + + return false; } const DisplayBuffer& Window::update_display_buffer(const Context& context) @@ -212,15 +215,11 @@ DisplaySetup Window::compute_display_setup(const Context& context) const const int tabstop = context.options()["tabstop"].get(); const auto& cursor = context.selections().main().cursor(); - bool ensure_cursor_visible = should_make_cursor_visible(context); - - if (ensure_cursor_visible) - { - if (cursor.line - offset.line < win_pos.line) - win_pos.line = std::max(0_line, cursor.line - offset.line); - if (cursor.line + offset.line >= win_pos.line + m_dimensions.line) - win_pos.line = std::min(buffer().line_count()-1, cursor.line + offset.line - m_dimensions.line + 1); - } + // Ensure cursor line is visible + if (cursor.line - offset.line < win_pos.line) + win_pos.line = std::max(0_line, cursor.line - offset.line); + if (cursor.line + offset.line >= win_pos.line + m_dimensions.line) + win_pos.line = std::min(buffer().line_count()-1, cursor.line + offset.line - m_dimensions.line + 1); DisplaySetup setup{ win_pos.line, @@ -229,15 +228,13 @@ DisplaySetup Window::compute_display_setup(const Context& context) const 0_col, {cursor.line - win_pos.line, get_column(buffer(), tabstop, cursor) - win_pos.column}, - offset, - ensure_cursor_visible + offset }; for (auto pass : { HighlightPass::Move, HighlightPass::Wrap }) m_builtin_highlighters.compute_display_setup({context, setup, pass, {}}, setup); check_display_setup(setup, *this); // now ensure the cursor column is visible - if (ensure_cursor_visible) { auto underflow = std::max(-setup.first_column, setup.cursor_pos.column - setup.scroll_offset.column); diff --git a/src/window.hh b/src/window.hh index 4a6a5e47..dd7a325b 100644 --- a/src/window.hh +++ b/src/window.hh @@ -43,7 +43,7 @@ public: Buffer& buffer() const { return *m_buffer; } bool needs_redraw(const Context& context) const; - void force_redraw() { m_last_setup.dimensions = {}; } + void force_redraw() { m_last_setup = Setup{}; } void set_client(Client* client) { m_client = client; } @@ -60,8 +60,6 @@ private: void run_hook_in_own_context(Hook hook, StringView param, String client_name = ""); - bool should_make_cursor_visible(const Context& context) const; - SafePtr m_buffer; SafePtr m_client; @@ -79,7 +77,7 @@ private: size_t timestamp; size_t faces_hash; size_t main_selection; - Vector selections; + Vector selections; }; Setup build_setup(const Context& context) const; Setup m_last_setup; diff --git a/test/regression/3219-scroll-json-ui/script b/test/regression/3219-scroll-json-ui/script index 2ba5f829..0cfd5b58 100644 --- a/test/regression/3219-scroll-json-ui/script +++ b/test/regression/3219-scroll-json-ui/script @@ -6,8 +6,8 @@ ui_out '{ "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { ui_out '{ "jsonrpc": "2.0", "method": "set_cursor", "params": ["buffer", { "line": 0, "column": 0 }] }' ui_out '{ "jsonrpc": "2.0", "method": "refresh", "params": [true] }' ui_in '{ "jsonrpc": "2.0", "method": "scroll", "params": [ 2 ] }' -ui_out '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "03\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "04\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "05\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "06\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "07\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "08\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "09\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "10\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "11\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "12\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "13\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "14\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "15\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "16\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "17\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "18\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "19\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "20\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "21\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "22\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "23\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "24\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "25\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "26\u000a" }]], { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }] }' +ui_out '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "black", "bg": "white", "underline": "default", "attributes": [] }, "contents": "0" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "3\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "04\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "05\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "06\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "07\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "08\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "09\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "10\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "11\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "12\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "13\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "14\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "15\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "16\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "17\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "18\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "19\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "20\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "21\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "22\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "23\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "24\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "25\u000a" }], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "26\u000a" }]], { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }] }' ui_out '{ "jsonrpc": "2.0", "method": "info_hide", "params": [] }' -ui_out '{ "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "out 1:1 " }, { "face": { "fg": "black", "bg": "yellow", "underline": "default", "attributes": [] }, "contents": "" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " - client0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "underline": "default", "attributes": [] }] }' +ui_out '{ "jsonrpc": "2.0", "method": "draw_status", "params": [[], [{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "out 3:1 " }, { "face": { "fg": "black", "bg": "yellow", "underline": "default", "attributes": [] }, "contents": "" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " " }, { "face": { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }, "contents": "1 sel" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": " - client0@[kak-tests]" }], { "fg": "cyan", "bg": "default", "underline": "default", "attributes": [] }] }' ui_out '{ "jsonrpc": "2.0", "method": "set_cursor", "params": ["buffer", { "line": 0, "column": 0 }] }' ui_out '{ "jsonrpc": "2.0", "method": "refresh", "params": [false] }' diff --git a/test/regression/4839-scroll-invalid-cursor/cmd b/test/regression/4839-scroll-invalid-cursor/cmd index 10ba8aba..ec0f73a0 100644 --- a/test/regression/4839-scroll-invalid-cursor/cmd +++ b/test/regression/4839-scroll-invalid-cursor/cmd @@ -1 +1 @@ -l +l diff --git a/test/regression/4839-scroll-invalid-cursor/script b/test/regression/4839-scroll-invalid-cursor/script index 31d58187..03227629 100644 --- a/test/regression/4839-scroll-invalid-cursor/script +++ b/test/regression/4839-scroll-invalid-cursor/script @@ -1,2 +1,2 @@ -ui_out -ignore 7 -ui_out '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "😃\u000a" }]], { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }] }' +ui_out -ignore 1 +ui_out '{ "jsonrpc": "2.0", "method": "draw", "params": [[[{ "face": { "fg": "black", "bg": "white", "underline": "default", "attributes": [] }, "contents": "😃" }, { "face": { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, "contents": "\u000a" }]], { "fg": "default", "bg": "default", "underline": "default", "attributes": [] }, { "fg": "blue", "bg": "default", "underline": "default", "attributes": [] }] }'