summaryrefslogtreecommitdiff
path: root/unity-shared
diff options
authorMarco Trevisan (TreviƱo) <mail@3v1n0.net>2015-12-11 12:44:45 +0000
committerCI Train Bot <ci-train-bot@canonical.com>2015-12-11 12:44:45 +0000
commit14e00d95b8d3c9b81a456d19b7dde9d563af412b (patch)
tree040f963c07713a4e17c83e0b952984c346278a67 /unity-shared
parent51a827e932f36ca51aaa432f9141a0fb1dec871c (diff)
parent317f6f87b2b7913cccbc130b691490b630d93447 (diff)
XKeyboardUtil: add ability to get keycodes from any relative position
Approved by: PS Jenkins bot, Andrea Azzarone (bzr r4040)
Diffstat (limited to 'unity-shared')
-rw-r--r--unity-shared/XKeyboardUtil.cpp204
-rw-r--r--unity-shared/XKeyboardUtil.h3
2 files changed, 160 insertions, 47 deletions
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 = &section->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 = &section->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 = &section->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);
}