diff options
| author | Marco Trevisan (TreviƱo) <mail@3v1n0.net> | 2015-12-11 12:44:45 +0000 |
|---|---|---|
| committer | CI Train Bot <ci-train-bot@canonical.com> | 2015-12-11 12:44:45 +0000 |
| commit | 14e00d95b8d3c9b81a456d19b7dde9d563af412b (patch) | |
| tree | 040f963c07713a4e17c83e0b952984c346278a67 | |
| parent | 51a827e932f36ca51aaa432f9141a0fb1dec871c (diff) | |
| parent | 317f6f87b2b7913cccbc130b691490b630d93447 (diff) | |
XKeyboardUtil: add ability to get keycodes from any relative position
Approved by: PS Jenkins bot, Andrea Azzarone (bzr r4040)
| -rw-r--r-- | tests/test_keyboard_util.cpp | 172 | ||||
| -rw-r--r-- | unity-shared/XKeyboardUtil.cpp | 204 | ||||
| -rw-r--r-- | unity-shared/XKeyboardUtil.h | 3 |
3 files changed, 296 insertions, 83 deletions
diff --git a/tests/test_keyboard_util.cpp b/tests/test_keyboard_util.cpp index f596f2af1..4e315b140 100644 --- a/tests/test_keyboard_util.cpp +++ b/tests/test_keyboard_util.cpp @@ -30,48 +30,148 @@ using namespace unity; namespace { -void test_key(Display* x_display, const char* key) +TEST(TestKeyboardUtil, AboveKeySymbol) { - KeySym keysym = XStringToKeysym(key); - KeySym above_keysym = keyboard::get_key_above_key_symbol(x_display, keysym); - EXPECT_NE(above_keysym, NoSymbol); + Display* x_display = XOpenDisplay(NULL); + + ASSERT_EQ(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("escape")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("Tab")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("Shift_R")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("Control_L")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("space")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("comma")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("a")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("b")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("c")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("d")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("e")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("f")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("g")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("h")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("i")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("j")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("k")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("l")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("m")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("n")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("o")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("p")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("k")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("r")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("s")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("t")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("u")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("v")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("w")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("x")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("y")), NoSymbol); + ASSERT_NE(keyboard::get_key_above_key_symbol(x_display, XStringToKeysym("z")), NoSymbol); } -TEST(TestKeyboardUtil, AboveKeySymbol) +TEST(TestKeyboardUtil, BelowKeySymbol) +{ + Display* x_display = XOpenDisplay(NULL); + + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("Tab")), NoSymbol); + ASSERT_EQ(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("Control_L")), NoSymbol); + ASSERT_EQ(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("space")), NoSymbol); + ASSERT_EQ(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("comma")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("a")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("b")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("d")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("e")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("f")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("g")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("h")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("i")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("j")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("k")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("l")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("o")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("p")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("k")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("r")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("s")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("t")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("u")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("w")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("x")), NoSymbol); + ASSERT_NE(keyboard::get_key_below_key_symbol(x_display, XStringToKeysym("y")), NoSymbol); +} + +TEST(TestKeyboardUtil, RightToKeySymbol) +{ + Display* x_display = XOpenDisplay(NULL); + + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("Tab")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("Shift_R")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("Control_L")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("space")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("comma")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("a")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("b")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("c")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("d")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("e")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("f")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("g")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("h")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("i")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("j")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("k")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("l")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("m")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("n")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("o")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("p")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("k")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("r")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("s")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("t")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("u")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("v")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("w")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("x")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("y")), NoSymbol); + ASSERT_NE(keyboard::get_key_right_to_key_symbol(x_display, XStringToKeysym("z")), NoSymbol); +} + +TEST(TestKeyboardUtil, LeftToKeySymbol) { Display* x_display = XOpenDisplay(NULL); - test_key(x_display, "Tab"); - test_key(x_display, "Shift_R"); - test_key(x_display, "Control_L"); - test_key(x_display, "space"); - test_key(x_display, "comma"); - test_key(x_display, "a"); - test_key(x_display, "b"); - test_key(x_display, "c"); - test_key(x_display, "d"); - test_key(x_display, "e"); - test_key(x_display, "f"); - test_key(x_display, "g"); - test_key(x_display, "h"); - test_key(x_display, "i"); - test_key(x_display, "j"); - test_key(x_display, "k"); - test_key(x_display, "l"); - test_key(x_display, "m"); - test_key(x_display, "n"); - test_key(x_display, "o"); - test_key(x_display, "p"); - test_key(x_display, "k"); - test_key(x_display, "r"); - test_key(x_display, "s"); - test_key(x_display, "t"); - test_key(x_display, "u"); - test_key(x_display, "v"); - test_key(x_display, "w"); - test_key(x_display, "x"); - test_key(x_display, "y"); - test_key(x_display, "z"); + ASSERT_EQ(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("Tab")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("Shift_R")), NoSymbol); + ASSERT_EQ(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("Control_L")), NoSymbol); + ASSERT_EQ(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("escape")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("space")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("comma")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("a")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("b")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("c")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("d")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("e")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("f")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("g")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("h")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("i")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("j")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("k")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("l")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("m")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("n")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("o")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("p")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("k")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("r")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("s")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("t")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("u")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("v")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("w")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("x")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("y")), NoSymbol); + ASSERT_NE(keyboard::get_key_left_to_key_symbol(x_display, XStringToKeysym("z")), NoSymbol); } TEST(TestKeyboardUtil, PrintableKeySymbols) diff --git a/unity-shared/XKeyboardUtil.cpp b/unity-shared/XKeyboardUtil.cpp index 039eba3a8..ec22361cd 100644 --- a/unity-shared/XKeyboardUtil.cpp +++ b/unity-shared/XKeyboardUtil.cpp @@ -1,6 +1,6 @@ // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- /* - * Copyright (C) 2011 Canonical Ltd + * Copyright (C) 2011-2015 Canonical Ltd * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as @@ -15,12 +15,15 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Authored by: Jason Smith <jason.smith@canonical.com> + * Marco Trevisan <marco.trevisan@canonical.com> */ #include <gdk/gdk.h> #include <string.h> #include <cmath> +#include <NuxCore/Logger.h> + #include <X11/keysym.h> #include <X11/XKBlib.h> #include <X11/extensions/XKBgeom.h> @@ -34,6 +37,8 @@ namespace keyboard { namespace { +DECLARE_LOGGER(logger, "unity.keyboard.xutil"); + const unsigned int FETCH_MASK = (XkbGBN_KeyNamesMask | XkbGBN_ClientSymbolsMask | XkbGBN_GeometryMask); @@ -44,16 +49,26 @@ public: KeyboardUtil(Display* display); ~KeyboardUtil(); - guint GetKeycodeAboveKeySymbol(KeySym key_symbol) const; + enum class Position + { + LEFT, + RIGHT, + ABOVE, + BELOW + }; + + KeyCode GetKeyCodeNearKeySymbol(KeySym key_symbol, Position) const; + KeySym GetNearKey(KeySym key_symbol, Position) const; private: - bool CompareOffsets (int current_x, int current_y, int best_x, int best_y) const; - guint ConvertKeyToKeycode (XkbKeyPtr key) const; + bool CompareOffsets(int current_x, int current_y, int best_x, int best_y) const; + KeyCode ConvertKeyToKeycode(XkbKeyPtr key) const; - bool FindKeyInGeometry(XkbGeometryPtr geo, char *key_name, int& res_section, XkbBoundsRec& res_bounds) const; - bool FindKeyInSectionAboveBounds (XkbGeometryPtr geo, int section, XkbBoundsRec const& target_bounds, guint &keycode) const; + bool FindKeyInGeometry(XkbGeometryPtr, char *key_name, int& res_section, XkbBoundsRec&) const; + bool FindKeyInVertical(Position, XkbGeometryPtr, int section, XkbBoundsRec const&, KeyCode&) const; + bool FindKeyOnSides(Position, XkbGeometryPtr, int section_index, XkbBoundsRec const&, KeyCode &keycode) const; - XkbBoundsRec GetAbsoluteKeyBounds (XkbKeyPtr key, XkbRowPtr row, XkbSectionPtr section, XkbGeometryPtr geo) const; + XkbBoundsRec GetAbsoluteKeyBounds (XkbKeyPtr, XkbRowPtr, XkbSectionPtr, XkbGeometryPtr) const; Display *display_; XkbDescPtr keyboard_; @@ -116,7 +131,7 @@ bool KeyboardUtil::CompareOffsets(int current_x, int current_y, int best_x, int return false; } -guint KeyboardUtil::ConvertKeyToKeycode(XkbKeyPtr key) const +KeyCode KeyboardUtil::ConvertKeyToKeycode(XkbKeyPtr key) const { if (!keyboard_) return 0; @@ -164,49 +179,111 @@ XkbBoundsRec KeyboardUtil::GetAbsoluteKeyBounds(XkbKeyPtr key, XkbRowPtr row, Xk return result; } -bool KeyboardUtil::FindKeyInSectionAboveBounds(XkbGeometryPtr geo, int section_index, XkbBoundsRec const& target_bounds, guint &keycode) const +bool KeyboardUtil::FindKeyInVertical(Position pos, XkbGeometryPtr geo, int section_index, XkbBoundsRec const& target_bounds, KeyCode &keycode) const { - XkbKeyPtr best = NULL; + XkbKeyPtr best = nullptr; int best_x_offset = G_MAXINT; int best_y_offset = G_MAXINT; int sections_in_geometry = geo->num_sections; - for (int k = 0; k < sections_in_geometry; k++) + for (int k = 0; k < sections_in_geometry; ++k) { + XkbSectionPtr section = &geo->sections[section_index]; + + for (int i = 0; i < section->num_rows; ++i) + { + XkbRowPtr row = §ion->rows[i]; + + int keys_in_row = row->num_keys; + for (int j = 0; j < keys_in_row; ++j) + { + XkbKeyPtr key = &row->keys[j]; + XkbBoundsRec bounds = GetAbsoluteKeyBounds(key, row, section, geo); + + // make sure we are actually over the target bounds + int hcenter = (bounds.x1 + bounds.x2) / 2; + if (hcenter < target_bounds.x1 || hcenter > target_bounds.x2) + continue; + + // make sure the key is actually above our target. + int current_y_offset; + + if (pos == Position::ABOVE) + current_y_offset = target_bounds.y1 - bounds.y2; + else // if (pos == Position::BELOW) + current_y_offset = bounds.y1 - target_bounds.y2; + + // make sure the key is actually above our target. + if (current_y_offset < 0) + continue; + + int current_x_offset = std::abs(hcenter - (target_bounds.x1 + target_bounds.x2) / 2); + + if (CompareOffsets(current_x_offset, current_y_offset, best_x_offset, best_y_offset)) + { + best = key; + best_x_offset = current_x_offset; + best_y_offset = current_y_offset; + } + } + } + } - XkbSectionPtr section = &geo->sections[section_index]; - int rows_in_section = section->num_rows; - for (int i = 0; i < rows_in_section; i++) + if (best) { - XkbRowPtr row = §ion->rows[i]; + keycode = ConvertKeyToKeycode(best); + return true; + } + return false; +} + +bool KeyboardUtil::FindKeyOnSides(Position pos, XkbGeometryPtr geo, int section_index, XkbBoundsRec const& target_bounds, KeyCode &keycode) const +{ + XkbKeyPtr best = nullptr; + int best_x_offset = G_MAXINT; + int best_y_offset = G_MAXINT; - int keys_in_row = row->num_keys; - for (int j = 0; j < keys_in_row; j++) + int sections_in_geometry = geo->num_sections; + for (int k = 0; k < sections_in_geometry; ++k) + { + XkbSectionPtr section = &geo->sections[section_index]; + for (int i = 0; i < section->num_rows; ++i) { - XkbKeyPtr key = &row->keys[j]; - XkbBoundsRec bounds = GetAbsoluteKeyBounds (key, row, section, geo); + XkbRowPtr row = §ion->rows[i]; - // make sure we are actually over the target bounds - int center = (bounds.x1 + bounds.x2) / 2; - if (center < target_bounds.x1 || center > target_bounds.x2) - continue; + int keys_in_row = row->num_keys; + for (int j = 0; j < keys_in_row; ++j) + { + XkbKeyPtr key = &row->keys[j]; + XkbBoundsRec bounds = GetAbsoluteKeyBounds(key, row, section, geo); - // make sure the key is actually above our target. - int current_y_offset = target_bounds.y1 - bounds.y2; - if (current_y_offset < 0) - continue; + // make sure we are actually over the target bounds + int vcenter = (bounds.y1 + bounds.y2) / 2; + if (vcenter < target_bounds.y1 || vcenter > target_bounds.y2) + continue; - int current_x_offset = std::abs(center - (target_bounds.x1 + target_bounds.x2) / 2); + int current_x_offset; - if (CompareOffsets(current_x_offset, current_y_offset, best_x_offset, best_y_offset)) - { - best = key; - best_x_offset = current_x_offset; - best_y_offset = current_y_offset; - } + if (pos == Position::LEFT) + current_x_offset = target_bounds.x1 - bounds.x2; + else // if (pos == Position::RIGHT) + current_x_offset = target_bounds.x2 - bounds.x1; + + // make sure the key is actually above our target. + if (current_x_offset < 0) + continue; + + int current_y_offset = std::abs(vcenter - (target_bounds.y1 + target_bounds.y2) / 2); + + if (CompareOffsets(current_x_offset, current_y_offset, best_x_offset, best_y_offset)) + { + best = key; + best_x_offset = current_x_offset; + best_y_offset = current_y_offset; + } + } } } - } if (best) { @@ -216,11 +293,10 @@ bool KeyboardUtil::FindKeyInSectionAboveBounds(XkbGeometryPtr geo, int section_i return false; } -guint KeyboardUtil::GetKeycodeAboveKeySymbol(KeySym key_symbol) const +KeyCode KeyboardUtil::GetKeyCodeNearKeySymbol(KeySym key_symbol, Position pos) const { - guint result = 0; - - int code = XKeysymToKeycode(display_, key_symbol); + KeyCode result = 0; + KeyCode code = XKeysymToKeycode(display_, key_symbol); if (!code || !keyboard_) return result; @@ -230,15 +306,30 @@ guint KeyboardUtil::GetKeycodeAboveKeySymbol(KeySym key_symbol) const char* key_str = keyboard_->names->keys[code].name; - int key_section; XkbBoundsRec key_bounds; bool found_key = FindKeyInGeometry(keyboard_->geom, key_str, key_section, key_bounds); if (found_key) { - guint maybe; - found_key = FindKeyInSectionAboveBounds(keyboard_->geom, key_section, key_bounds, maybe); + KeyCode maybe; + + switch (pos) + { + case Position::LEFT: + case Position::RIGHT: + found_key = FindKeyOnSides(pos, keyboard_->geom, key_section, key_bounds, maybe); + break; + case Position::ABOVE: + case Position::BELOW: + found_key = FindKeyInVertical(pos, keyboard_->geom, key_section, key_bounds, maybe); + break; + default: + LOG_ERROR(logger) << "Impossible to find key near to " << XKeysymToString(key_symbol) + << " at position " << static_cast<unsigned>(pos); // Get actual type name. + found_key = false; + break; + } if (found_key) result = maybe; @@ -247,6 +338,14 @@ guint KeyboardUtil::GetKeycodeAboveKeySymbol(KeySym key_symbol) const return result; } +KeySym KeyboardUtil::GetNearKey(KeySym key_symbol, Position pos) const +{ + KeyCode keycode = GetKeyCodeNearKeySymbol(key_symbol, pos); + const unsigned int group_interest = 0; + const unsigned int shift_interest = 0; + return XkbKeycodeToKeysym(display_, keycode, group_interest, shift_interest); +} + } // anon namespace @@ -277,11 +376,22 @@ bool is_move_key_symbol(unsigned long key_symbol) KeySym get_key_above_key_symbol(Display* display, KeySym key_symbol) { - KeyboardUtil util(display); - guint above_keycode = util.GetKeycodeAboveKeySymbol(key_symbol); - const unsigned int group_interest = 0; - const unsigned int shift_interest = 0; - return XkbKeycodeToKeysym(display, above_keycode, group_interest, shift_interest); + return KeyboardUtil(display).GetNearKey(key_symbol, KeyboardUtil::Position::ABOVE); +} + +KeySym get_key_below_key_symbol(Display* display, KeySym key_symbol) +{ + return KeyboardUtil(display).GetNearKey(key_symbol, KeyboardUtil::Position::BELOW); +} + +KeySym get_key_right_to_key_symbol(Display* display, KeySym key_symbol) +{ + return KeyboardUtil(display).GetNearKey(key_symbol, KeyboardUtil::Position::RIGHT); +} + +KeySym get_key_left_to_key_symbol(Display* display, KeySym key_symbol) +{ + return KeyboardUtil(display).GetNearKey(key_symbol, KeyboardUtil::Position::LEFT); } } // namespace keyboard diff --git a/unity-shared/XKeyboardUtil.h b/unity-shared/XKeyboardUtil.h index 230bd834a..b71169a9c 100644 --- a/unity-shared/XKeyboardUtil.h +++ b/unity-shared/XKeyboardUtil.h @@ -28,6 +28,9 @@ namespace keyboard { KeySym get_key_above_key_symbol(Display* display, KeySym key_symbol); +KeySym get_key_below_key_symbol(Display* display, KeySym key_symbol); +KeySym get_key_right_to_key_symbol(Display* display, KeySym key_symbol); +KeySym get_key_left_to_key_symbol(Display* display, KeySym key_symbol); } |
