Make scrolling speed configurable

The UI now can send a 'Scroll' key, whose value is the scrolling
amount encoded as a signed integer. This replaces the MouseWheelUp
and MouseWheelDown keys.

The NCursesUI now has a ncurses_wheel_scroll_amount ui_option that
controls that amount, it can be negative to swap scrolling direction.

Fixes #3045
This commit is contained in:
Maxime Coste 2019-08-19 22:16:39 +10:00
parent f1047181cb
commit 2359df0f17
7 changed files with 68 additions and 82 deletions

View File

@ -92,8 +92,7 @@ struct MouseHandler
Buffer& buffer = context.buffer();
BufferCoord cursor;
auto& selections = context.selections();
const auto key_modifier = (Key::Modifiers)(key.modifiers & Key::Modifiers::MouseEvent);
switch (key_modifier)
switch (key.modifiers)
{
case Key::Modifiers::MousePressRight:
m_dragging = false;
@ -137,14 +136,9 @@ struct MouseHandler
selections.sort_and_merge_overlapping();
return true;
case Key::Modifiers::MouseWheelDown:
case Key::Modifiers::Scroll:
m_dragging = false;
scroll_window(context, 3);
return true;
case Key::Modifiers::MouseWheelUp:
m_dragging = false;
scroll_window(context, -3);
scroll_window(context, static_cast<int32_t>(key.key));
return true;
default: return false;
@ -232,16 +226,6 @@ public:
kak_assert(m_state != State::PopOnEnabled);
ScopedSetBool set_in_on_key{m_in_on_key};
// Hack to parse keys sent by terminals using the 8th bit to mark the
// meta key. In normal mode, give priority to a potential alt-key than
// the accentuated character.
if (not (key.modifiers & Key::Modifiers::MouseEvent) and
key.key >= 127 and key.key < 256)
{
key.modifiers |= Key::Modifiers::Alt;
key.key &= 0x7f;
}
bool do_restore_hooks = false;
auto restore_hooks = on_scope_end([&, this]{
if (m_hooks_disabled and enabled() and do_restore_hooks)
@ -253,8 +237,6 @@ public:
const bool transient = context().flags() & Context::Flags::Draft;
auto cp = key.codepoint();
if (m_mouse_handler.handle_key(key, context()))
{
context().print_status({});
@ -264,7 +246,7 @@ public:
if (not transient)
m_idle_timer.set_next_date(Clock::now() + get_idle_timeout(context()));
}
else if (cp and isdigit(*cp))
else if (auto cp = key.codepoint(); cp and isdigit(*cp))
{
long long new_val = (long long)m_params.count * 10 + *cp - '0';
if (new_val > std::numeric_limits<int>::max())
@ -310,6 +292,15 @@ public:
if (context().has_client())
context().client().info_hide();
// Hack to parse keys sent by terminals using the 8th bit to mark the
// meta key. In normal mode, give priority to a potential alt-key than
// the accentuated character.
if (key.key >= 127 and key.key < 256)
{
key.modifiers |= Key::Modifiers::Alt;
key.key &= 0x7f;
}
do_restore_hooks = true;
if (auto command = get_normal_command(key))
{

View File

@ -430,13 +430,18 @@ void JsonUI::eval_json(const Value& json)
m_on_key({Key::Modifiers::MouseReleaseLeft, coord});
else if (type == "release_right")
m_on_key({Key::Modifiers::MouseReleaseRight, coord});
else if (type == "wheel_up")
m_on_key({Key::Modifiers::MouseWheelUp, coord});
else if (type == "wheel_down")
m_on_key({Key::Modifiers::MouseWheelDown, coord});
else
throw invalid_rpc_request(format("invalid mouse event type: {}", type));
}
else if (method == "scroll")
{
if (params.size() != 1)
throw invalid_rpc_request("scroll needs an amount");
else if (not params[0].is_a<int>())
throw invalid_rpc_request("scroll amount is not an integer");
m_on_key({Key::Modifiers::Scroll, (Codepoint)params[0].as<int>()});
}
else if (method == "menu_select")
{
if (params.size() != 1)

View File

@ -145,11 +145,9 @@ KeyList parse_keys(StringView str)
}
String key_to_str(Key key)
{
if (auto mouse_event = (key.modifiers & Key::Modifiers::MouseEvent))
{
const auto coord = key.coord() + DisplayCoord{1,1};
switch ((Key::Modifiers)mouse_event)
switch (key.modifiers)
{
case Key::Modifiers::MousePos:
return format("<mouse:move:{}.{}>", coord.line, coord.column);
@ -161,17 +159,11 @@ String key_to_str(Key key)
return format("<mouse:release_left:{}.{}>", coord.line, coord.column);
case Key::Modifiers::MouseReleaseRight:
return format("<mouse:release_right:{}.{}>", coord.line, coord.column);
case Key::Modifiers::MouseWheelDown:
return "<mouse:wheel_down>";
case Key::Modifiers::MouseWheelUp:
return "<mouse:wheel_up>";
default: kak_assert(false);
}
}
else if (key.modifiers == Key::Modifiers::Resize)
{
auto size = key.coord() + DisplayCoord{1,1};
return format("<resize:{}.{}>", size.line, size.column);
case Key::Modifiers::Scroll:
return format("<scroll:{}>", static_cast<int>(key.key));
case Key::Modifiers::Resize:
return format("<resize:{}.{}>", coord.line, coord.column);
default: break;
}
bool named = false;

View File

@ -26,14 +26,9 @@ struct Key
MouseReleaseLeft = 1 << 5,
MouseReleaseRight = 1 << 6,
MousePos = 1 << 7,
MouseWheelDown = 1 << 8,
MouseWheelUp = 1 << 9,
MouseEvent = MousePressLeft | MousePressRight |
MouseReleaseLeft | MouseReleaseRight |
MousePos | MouseWheelDown | MouseWheelUp,
Resize = 1 << 10,
MenuSelect = 1 << 11,
Scroll = 1 << 8,
Resize = 1 << 9,
MenuSelect = 1 << 10,
};
enum NamedKey : Codepoint
{

View File

@ -437,6 +437,7 @@ void register_options()
" ncurses_change_colors bool\n"
" ncurses_wheel_up_button int\n"
" ncurses_wheel_down_button int\n"
" ncurses_wheel_scroll_amount int\n"
" ncurses_shift_function_key int\n"
" ncurses_builtin_key_parser bool\n",
UserInterface::Options{});

View File

@ -556,31 +556,28 @@ Optional<Key> NCursesUI::get_next_key()
MEVENT ev;
if (getmouse(&ev) == OK)
{
auto get_modifiers = [this](mmask_t mask) {
Key::Modifiers res{};
const auto mask = ev.bstate;
auto coord = encode_coord({ ev.y - content_line_offset(), ev.x });
Key::Modifiers mod{};
if (mask & BUTTON_CTRL)
res |= Key::Modifiers::Control;
mod |= Key::Modifiers::Control;
if (mask & BUTTON_ALT)
res |= Key::Modifiers::Alt;
mod |= Key::Modifiers::Alt;
if (BUTTON_PRESS(mask, 1))
return res | Key::Modifiers::MousePressLeft;
return Key{mod | Key::Modifiers::MousePressLeft, coord};
if (BUTTON_PRESS(mask, 3))
return res | Key::Modifiers::MousePressRight;
return Key{mod | Key::Modifiers::MousePressRight, coord};
if (BUTTON_RELEASE(mask, 1))
return res | Key::Modifiers::MouseReleaseLeft;
return Key{mod | Key::Modifiers::MouseReleaseLeft, coord};
if (BUTTON_RELEASE(mask, 3))
return res | Key::Modifiers::MouseReleaseRight;
return Key{mod | Key::Modifiers::MouseReleaseRight, coord};
if (BUTTON_PRESS(mask, m_wheel_down_button))
return res | Key::Modifiers::MouseWheelDown;
return Key{mod | Key::Modifiers::Scroll, static_cast<Codepoint>(m_wheel_scroll_amount)};
if (BUTTON_PRESS(mask, m_wheel_up_button))
return res | Key::Modifiers::MouseWheelUp;
return res | Key::Modifiers::MousePos;
};
return Key{ get_modifiers(ev.bstate),
encode_coord({ ev.y - content_line_offset(), ev.x }) };
return Key{mod | Key::Modifiers::Scroll, static_cast<Codepoint>(-m_wheel_scroll_amount)};
return Key{mod | Key::Modifiers::MousePos, coord};
}
}
@ -1278,6 +1275,10 @@ void NCursesUI::set_ui_options(const Options& options)
auto wheel_down_it = options.find("ncurses_wheel_down_button"_sv);
m_wheel_down_button = wheel_down_it != options.end() ?
str_to_int_ifp(wheel_down_it->value).value_or(5) : 5;
auto wheel_scroll_amount_it = options.find("ncurses_wheel_scroll_amount"_sv);
m_wheel_scroll_amount = wheel_scroll_amount_it != options.end() ?
str_to_int_ifp(wheel_scroll_amount_it->value).value_or(3) : 3;
}
{

View File

@ -140,6 +140,7 @@ private:
bool m_mouse_enabled = false;
int m_wheel_up_button = 4;
int m_wheel_down_button = 5;
int m_wheel_scroll_amount = 3;
static constexpr int default_shift_function_key = 12;
int m_shift_function_key = default_shift_function_key;