diff --git a/src/rime/gear/selector.cc b/src/rime/gear/selector.cc index 5dc38e637..f45d37cdc 100644 --- a/src/rime/gear/selector.cc +++ b/src/rime/gear/selector.cc @@ -16,6 +16,14 @@ namespace rime { +// Direction of candidate list. +using Direction = int; +constexpr Direction kDirectionVoid = -1; +constexpr Direction kDirectionDown = 0; +constexpr Direction kDirectionLeft = 1; +constexpr Direction kDirectionUp = 2; +constexpr Direction kDirectionRight = 3; + Selector::Selector(const Ticket& ticket) : Processor(ticket) { } @@ -28,6 +36,25 @@ ProcessResult Selector::ProcessKeyEvent(const KeyEvent& key_event) { Segment& current_segment(ctx->composition().back()); if (!current_segment.menu || current_segment.HasTag("raw")) return kNoop; + bool is_linear_candidate_list = ctx->get_option("_linear"); + bool is_vertical_text = ctx->get_option("_vertical"); + // Deprecated. equivalent to {_linear: true, _vertical: false} + bool is_horizontal_layout = ctx->get_option("_horizontal"); + Direction next_candidate = kDirectionDown; + Direction next_page = kDirectionDown; + if (is_vertical_text) { + // +90 degrees + next_candidate = (next_candidate + 1) % 4; + next_page = (next_page + 1) % 4; + } + if (is_linear_candidate_list || is_horizontal_layout) { + // -90 degrees + next_candidate = (next_candidate + 3) % 4; + } + if (next_page == next_candidate) { + // this is no-op. just to clarify that arrow keys don't change page. + next_page = kDirectionVoid; + } int ch = key_event.keycode(); if (ch == XK_Prior || ch == XK_KP_Prior) { PageUp(ctx); @@ -38,18 +65,18 @@ ProcessResult Selector::ProcessKeyEvent(const KeyEvent& key_event) { return kAccepted; } if (ch == XK_Up || ch == XK_KP_Up) { - if (ctx->get_option("_horizontal")) { - PageUp(ctx); - } else { + if (next_candidate == kDirectionDown) { CursorUp(ctx); + } else if (next_page == kDirectionDown) { + PageUp(ctx); } return kAccepted; } if (ch == XK_Down || ch == XK_KP_Down) { - if (ctx->get_option("_horizontal")) { - PageDown(ctx); - } else { + if (next_candidate == kDirectionDown) { CursorDown(ctx); + } else if (next_page == kDirectionDown) { + PageDown(ctx); } return kAccepted; } @@ -57,14 +84,18 @@ ProcessResult Selector::ProcessKeyEvent(const KeyEvent& key_event) { if (!key_event.ctrl() && !key_event.shift() && ctx->caret_pos() == ctx->input().length()) { - if (ctx->get_option("_horizontal") && + if (next_candidate == kDirectionRight && CursorUp(ctx)) { return kAccepted; } - if (ctx->get_option("_vertical")) { + if (next_candidate == kDirectionLeft) { CursorDown(ctx); return kAccepted; } + if (next_page == kDirectionLeft) { + PageDown(ctx); + return kAccepted; + } } return kNoop; } @@ -72,12 +103,16 @@ ProcessResult Selector::ProcessKeyEvent(const KeyEvent& key_event) { if (!key_event.ctrl() && !key_event.shift() && ctx->caret_pos() == ctx->input().length()) { - if (ctx->get_option("_horizontal")) { + if (next_candidate == kDirectionRight) { CursorDown(ctx); return kAccepted; } - if (ctx->get_option("_vertical") && - CursorUp(ctx)) { + if (next_candidate == kDirectionLeft) { + CursorUp(ctx); + return kAccepted; + } + if (next_page == kDirectionLeft) { + PageUp(ctx); return kAccepted; } }