Do not make cursor visible after mouse scrolling and view commands
ensure cursor is visible after user input except if the command implementation opted-out. Hooks and timers should not enforce visible cursor. PageUp/PageDown and `<c-f>` / `<c-b>` commands still move the cursor as this seemed a desired behaviour.
This commit is contained in:
parent
6990270005
commit
20a2bca52e
|
@ -109,7 +109,10 @@ bool Client::process_pending_inputs()
|
||||||
else if (key == Key::FocusOut)
|
else if (key == Key::FocusOut)
|
||||||
context().hooks().run_hook(Hook::FocusOut, context().name(), context());
|
context().hooks().run_hook(Hook::FocusOut, context().name(), context());
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
context().ensure_cursor_visible = true;
|
||||||
m_input_handler.handle_key(key);
|
m_input_handler.handle_key(key);
|
||||||
|
}
|
||||||
|
|
||||||
context().hooks().run_hook(Hook::RawKey, to_string(key), context());
|
context().hooks().run_hook(Hook::RawKey, to_string(key), context());
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,6 +144,8 @@ public:
|
||||||
void repeat_last_select() { if (m_last_select) m_last_select(*this); }
|
void repeat_last_select() { if (m_last_select) m_last_select(*this); }
|
||||||
|
|
||||||
Buffer* last_buffer() const;
|
Buffer* last_buffer() const;
|
||||||
|
|
||||||
|
bool ensure_cursor_visible = true;
|
||||||
private:
|
private:
|
||||||
void begin_edition();
|
void begin_edition();
|
||||||
void end_edition();
|
void end_edition();
|
||||||
|
|
|
@ -46,6 +46,7 @@ struct DisplaySetup
|
||||||
DisplayCoord cursor_pos;
|
DisplayCoord cursor_pos;
|
||||||
// Offset of line and columns that must remain visible around cursor
|
// Offset of line and columns that must remain visible around cursor
|
||||||
DisplayCoord scroll_offset;
|
DisplayCoord scroll_offset;
|
||||||
|
bool ensure_cursor_visible;
|
||||||
};
|
};
|
||||||
|
|
||||||
using HighlighterIdList = ConstArrayView<StringView>;
|
using HighlighterIdList = ConstArrayView<StringView>;
|
||||||
|
|
|
@ -752,7 +752,8 @@ struct WrapHighlighter : Highlighter
|
||||||
win_line += wrap_count + 1;
|
win_line += wrap_count + 1;
|
||||||
|
|
||||||
// scroll window to keep cursor visible, and update range as lines gets removed
|
// scroll window to keep cursor visible, and update range as lines gets removed
|
||||||
while (buf_line >= cursor.line and setup.first_line < cursor.line and
|
while (setup.ensure_cursor_visible and
|
||||||
|
buf_line >= cursor.line and setup.first_line < cursor.line and
|
||||||
setup.cursor_pos.line + setup.scroll_offset.line >= win_height)
|
setup.cursor_pos.line + setup.scroll_offset.line >= win_height)
|
||||||
{
|
{
|
||||||
auto remove_count = 1 + line_wrap_count(setup.first_line, indent);
|
auto remove_count = 1 + line_wrap_count(setup.first_line, indent);
|
||||||
|
@ -1660,7 +1661,8 @@ private:
|
||||||
setup.cursor_pos.column += cursor_move;
|
setup.cursor_pos.column += cursor_move;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last.line >= setup.first_line and
|
if (setup.ensure_cursor_visible and
|
||||||
|
last.line >= setup.first_line and
|
||||||
range.first.line <= setup.first_line + setup.line_count and
|
range.first.line <= setup.first_line + setup.line_count and
|
||||||
range.first.line != last.line)
|
range.first.line != last.line)
|
||||||
{
|
{
|
||||||
|
|
|
@ -180,7 +180,7 @@ struct MouseHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
case Key::Modifiers::Scroll:
|
case Key::Modifiers::Scroll:
|
||||||
scroll_window(context, static_cast<int32_t>(key.key), (bool)m_dragging);
|
scroll_window(context, static_cast<int32_t>(key.key), m_dragging ? OnHiddenCursor::MoveCursor : OnHiddenCursor::PreserveSelections);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default: return false;
|
default: return false;
|
||||||
|
@ -1852,7 +1852,7 @@ void hide_auto_info_ifn(const Context& context, bool hide)
|
||||||
context.client().info_hide();
|
context.client().info_hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
void scroll_window(Context& context, LineCount offset, bool mouse_dragging)
|
void scroll_window(Context& context, LineCount offset, OnHiddenCursor on_hidden_cursor)
|
||||||
{
|
{
|
||||||
Window& window = context.window();
|
Window& window = context.window();
|
||||||
Buffer& buffer = context.buffer();
|
Buffer& buffer = context.buffer();
|
||||||
|
@ -1861,6 +1861,9 @@ void scroll_window(Context& context, LineCount offset, bool mouse_dragging)
|
||||||
DisplayCoord win_pos = window.position();
|
DisplayCoord win_pos = window.position();
|
||||||
DisplayCoord win_dim = window.dimensions();
|
DisplayCoord win_dim = window.dimensions();
|
||||||
|
|
||||||
|
if (on_hidden_cursor == OnHiddenCursor::PreserveSelections)
|
||||||
|
context.ensure_cursor_visible = false;
|
||||||
|
|
||||||
if ((offset < 0 and win_pos.line == 0) or (offset > 0 and win_pos.line == line_count - 1))
|
if ((offset < 0 and win_pos.line == 0) or (offset > 0 and win_pos.line == line_count - 1))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1870,25 +1873,27 @@ void scroll_window(Context& context, LineCount offset, bool mouse_dragging)
|
||||||
|
|
||||||
win_pos.line = clamp(win_pos.line + offset, 0_line, line_count-1);
|
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<int>();
|
|
||||||
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);
|
window.set_position(win_pos);
|
||||||
main_selection = { new_anchor, new_cursor };
|
if (on_hidden_cursor != OnHiddenCursor::PreserveSelections)
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
|
||||||
selections.sort_and_merge_overlapping();
|
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<int>();
|
||||||
|
auto new_cursor = buffer.offset_coord(cursor, line - cursor.line, tabstop);
|
||||||
|
|
||||||
|
main_selection = {on_hidden_cursor == OnHiddenCursor::MoveCursor ? anchor : new_cursor, new_cursor};
|
||||||
|
|
||||||
|
selections.sort_and_merge_overlapping();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,7 +204,13 @@ void on_next_key_with_autoinfo(const Context& context, StringView mode_name,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void scroll_window(Context& context, LineCount offset, bool mouse_dragging = false);
|
enum class OnHiddenCursor {
|
||||||
|
PreserveSelections,
|
||||||
|
MoveCursor,
|
||||||
|
MoveCursorAndAnchor,
|
||||||
|
};
|
||||||
|
|
||||||
|
void scroll_window(Context& context, LineCount offset, OnHiddenCursor on_hidden_cursor);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -368,6 +368,7 @@ void view_commands(Context& context, NormalParams params)
|
||||||
const int count = params.count;
|
const int count = params.count;
|
||||||
on_next_key_with_autoinfo(context, "view", KeymapMode::View,
|
on_next_key_with_autoinfo(context, "view", KeymapMode::View,
|
||||||
[count](Key key, Context& context) {
|
[count](Key key, Context& context) {
|
||||||
|
context.ensure_cursor_visible = false;
|
||||||
if (key == Key::Escape)
|
if (key == Key::Escape)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -400,10 +401,10 @@ void view_commands(Context& context, NormalParams params)
|
||||||
window.scroll(-std::max<ColumnCount>(1, count));
|
window.scroll(-std::max<ColumnCount>(1, count));
|
||||||
break;
|
break;
|
||||||
case 'j':
|
case 'j':
|
||||||
scroll_window(context, std::max<LineCount>(1, count));
|
scroll_window(context, std::max<LineCount>(1, count), OnHiddenCursor::PreserveSelections);
|
||||||
break;
|
break;
|
||||||
case 'k':
|
case 'k':
|
||||||
scroll_window(context, -std::max<LineCount>(1, count));
|
scroll_window(context, -std::max<LineCount>(1, count), OnHiddenCursor::PreserveSelections);
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
window.scroll( std::max<ColumnCount>(1, count));
|
window.scroll( std::max<ColumnCount>(1, count));
|
||||||
|
@ -1408,7 +1409,7 @@ void scroll(Context& context, NormalParams params)
|
||||||
const int count = params.count ? params.count : 1;
|
const int count = params.count ? params.count : 1;
|
||||||
const LineCount offset = (window.dimensions().line - 2) / (half ? 2 : 1) * count;
|
const LineCount offset = (window.dimensions().line - 2) / (half ? 2 : 1) * count;
|
||||||
|
|
||||||
scroll_window(context, offset * direction);
|
scroll_window(context, offset * direction, OnHiddenCursor::MoveCursorAndAnchor);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<Direction direction>
|
template<Direction direction>
|
||||||
|
|
|
@ -202,11 +202,14 @@ DisplaySetup Window::compute_display_setup(const Context& context) const
|
||||||
const int tabstop = context.options()["tabstop"].get<int>();
|
const int tabstop = context.options()["tabstop"].get<int>();
|
||||||
const auto& cursor = context.selections().main().cursor();
|
const auto& cursor = context.selections().main().cursor();
|
||||||
|
|
||||||
// Ensure cursor line is visible
|
bool ensure_cursor_visible = context.ensure_cursor_visible;
|
||||||
if (cursor.line - offset.line < win_pos.line)
|
if (ensure_cursor_visible)
|
||||||
win_pos.line = std::max(0_line, cursor.line - offset.line);
|
{
|
||||||
if (cursor.line + offset.line >= win_pos.line + m_dimensions.line)
|
if (cursor.line - offset.line < win_pos.line)
|
||||||
win_pos.line = std::min(buffer().line_count()-1, cursor.line + offset.line - m_dimensions.line + 1);
|
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{
|
DisplaySetup setup{
|
||||||
win_pos.line,
|
win_pos.line,
|
||||||
|
@ -215,13 +218,15 @@ DisplaySetup Window::compute_display_setup(const Context& context) const
|
||||||
0_col,
|
0_col,
|
||||||
{cursor.line - win_pos.line,
|
{cursor.line - win_pos.line,
|
||||||
get_column(buffer(), tabstop, cursor) - win_pos.column},
|
get_column(buffer(), tabstop, cursor) - win_pos.column},
|
||||||
offset
|
offset,
|
||||||
|
ensure_cursor_visible
|
||||||
};
|
};
|
||||||
for (auto pass : { HighlightPass::Move, HighlightPass::Wrap })
|
for (auto pass : { HighlightPass::Move, HighlightPass::Wrap })
|
||||||
m_builtin_highlighters.compute_display_setup({context, setup, pass, {}}, setup);
|
m_builtin_highlighters.compute_display_setup({context, setup, pass, {}}, setup);
|
||||||
check_display_setup(setup, *this);
|
check_display_setup(setup, *this);
|
||||||
|
|
||||||
// now ensure the cursor column is visible
|
// now ensure the cursor column is visible
|
||||||
|
if (ensure_cursor_visible)
|
||||||
{
|
{
|
||||||
auto underflow = std::max(-setup.first_column,
|
auto underflow = std::max(-setup.first_column,
|
||||||
setup.cursor_pos.column - setup.scroll_offset.column);
|
setup.cursor_pos.column - setup.scroll_offset.column);
|
||||||
|
|
|
@ -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": "set_cursor", "params": ["buffer", { "line": 0, "column": 0 }] }'
|
||||||
ui_out '{ "jsonrpc": "2.0", "method": "refresh", "params": [true] }'
|
ui_out '{ "jsonrpc": "2.0", "method": "refresh", "params": [true] }'
|
||||||
ui_in '{ "jsonrpc": "2.0", "method": "scroll", "params": [ 2 ] }'
|
ui_in '{ "jsonrpc": "2.0", "method": "scroll", "params": [ 2 ] }'
|
||||||
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": "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": "info_hide", "params": [] }'
|
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 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": "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": "set_cursor", "params": ["buffer", { "line": 0, "column": 0 }] }'
|
ui_out '{ "jsonrpc": "2.0", "method": "set_cursor", "params": ["buffer", { "line": 0, "column": 0 }] }'
|
||||||
ui_out '{ "jsonrpc": "2.0", "method": "refresh", "params": [false] }'
|
ui_out '{ "jsonrpc": "2.0", "method": "refresh", "params": [false] }'
|
||||||
|
|
Loading…
Reference in New Issue
Block a user