summaryrefslogtreecommitdiffstats
path: root/gui/keyboard.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gui/keyboard.cpp')
-rw-r--r--gui/keyboard.cpp105
1 files changed, 84 insertions, 21 deletions
diff --git a/gui/keyboard.cpp b/gui/keyboard.cpp
index e55fb1b66..3b8fdc9ae 100644
--- a/gui/keyboard.cpp
+++ b/gui/keyboard.cpp
@@ -16,6 +16,7 @@
along with TWRP. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <linux/input.h>
#include <stdlib.h>
#include <string.h>
#include "../data.hpp"
@@ -31,13 +32,15 @@ extern "C" {
#include "rapidxml.hpp"
#include "objects.hpp"
+bool GUIKeyboard::CtrlActive = false;
+
GUIKeyboard::GUIKeyboard(xml_node<>* node)
: GUIObject(node)
{
int layoutindex, rowindex, keyindex, Xindex, Yindex, keyHeight = 0, keyWidth = 0;
currentKey = NULL;
highlightRenderCount = 0;
- hasHighlight = hasCapsHighlight = false;
+ hasHighlight = hasCapsHighlight = hasCtrlHighlight = false;
char resource[10], layout[8], row[5], key[6], longpress[7];
xml_attribute<>* attr;
xml_node<>* child;
@@ -58,6 +61,7 @@ GUIKeyboard::GUIKeyboard(xml_node<>* node)
mHighlightColor = LoadAttrColor(FindNode(node, "highlight"), "color", &hasHighlight);
mCapsHighlightColor = LoadAttrColor(FindNode(node, "capshighlight"), "color", &hasCapsHighlight);
+ mCtrlHighlightColor = LoadAttrColor(FindNode(node, "ctrlhighlight"), "color", &hasCtrlHighlight);
child = FindNode(node, "keymargin");
mKeyMarginX = LoadAttrIntScaleX(child, "x", 0);
@@ -228,10 +232,11 @@ int GUIKeyboard::ParseKey(const char* keyinfo, Key& key, int& Xindex, int keyWid
keychar = *ptr;
} else if (*ptr == 'c') { // This is an ASCII character code: "c:{number}"
keychar = atoi(ptr + 2);
+ } else if (*ptr == 'k') { // This is a Linux keycode from input.h: "k:{number}"
+ keychar = -atoi(ptr + 2);
} else if (*ptr == 'l') { // This is a different layout: "layout{number}"
- keychar = KEYBOARD_LAYOUT;
key.layout = atoi(ptr + 6);
- } else if (*ptr == 'a') { // This is an action: "action"
+ } else if (*ptr == 'a') { // This is an action: "action" (the Enter key)
keychar = KEYBOARD_ACTION;
} else
return -1;
@@ -273,8 +278,8 @@ void GUIKeyboard::LoadKeyLabels(xml_node<>* parent, int layout)
void GUIKeyboard::DrawKey(Key& key, int keyX, int keyY, int keyW, int keyH)
{
- unsigned char keychar = key.key;
- if (!keychar)
+ int keychar = key.key;
+ if (!keychar && !key.layout)
return;
// key background
@@ -291,7 +296,13 @@ void GUIKeyboard::DrawKey(Key& key, int keyX, int keyY, int keyW, int keyH)
string labelText;
ImageResource* labelImage = NULL;
if (keychar > 32 && keychar < 127) {
+ // TODO: this will eventually need UTF-8 support
labelText = (char) keychar;
+ if (CtrlActive) {
+ int ctrlchar = KeyCharToCtrlChar(keychar);
+ if (ctrlchar != keychar)
+ labelText = std::string("^") + (char)(ctrlchar + 64);
+ }
gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, mFontColor.alpha);
}
else {
@@ -343,6 +354,15 @@ void GUIKeyboard::DrawKey(Key& key, int keyX, int keyY, int keyW, int keyH)
}
}
+int GUIKeyboard::KeyCharToCtrlChar(int key)
+{
+ // convert upper and lower case to ctrl chars
+ // Ctrl+A to Ctrl+_ (we don't support entering null bytes)
+ if (key >= 65 && key <= 127 && key != 96)
+ return key & 0x1f;
+ return key; // pass on others (already ctrl chars, numbers, etc.) unchanged
+}
+
int GUIKeyboard::Render(void)
{
if (!isConditionTrue())
@@ -385,11 +405,17 @@ int GUIKeyboard::Render(void)
DrawKey(key, keyX, keyY, keyW, keyH);
// Draw highlight for capslock
- if (hasCapsHighlight && lay.is_caps && CapsLockOn && (int)key.key == KEYBOARD_LAYOUT && key.layout == lay.revert_layout) {
+ if (hasCapsHighlight && lay.is_caps && CapsLockOn && key.layout > 0 && key.layout == lay.revert_layout) {
gr_color(mCapsHighlightColor.red, mCapsHighlightColor.green, mCapsHighlightColor.blue, mCapsHighlightColor.alpha);
gr_fill(keyX, keyY, keyW, keyH);
}
+ // Draw highlight for control
+ if (hasCtrlHighlight && key.key == -KEY_LEFTCTRL && CtrlActive) {
+ gr_color(mCtrlHighlightColor.red, mCtrlHighlightColor.green, mCtrlHighlightColor.blue, mCtrlHighlightColor.alpha);
+ gr_fill(keyX, keyY, keyW, keyH);
+ }
+
// Highlight current key
if (hasHighlight && &key == currentKey && highlightRenderCount != 0) {
gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, mHighlightColor.alpha);
@@ -444,7 +470,7 @@ GUIKeyboard::Key* GUIKeyboard::HitTestKey(int x, int y)
int x1 = 0;
for (col = 0; col < MAX_KEYBOARD_KEYS; ++col) {
Key& key = lay.keys[row][col];
- if (x1 <= relx && relx < key.end_x && key.key != 0) {
+ if (x1 <= relx && relx < key.end_x && (key.key != 0 || key.layout != 0)) {
// This is the key that was pressed!
return &key;
}
@@ -476,19 +502,20 @@ int GUIKeyboard::NotifyTouch(TOUCH_STATE state, int x, int y)
break;
case TOUCH_RELEASE:
+ // TODO: we might want to notify of key releases here
if (x < startX - (mRenderW * 0.5)) {
if (highlightRenderCount != 0) {
highlightRenderCount = 0;
mRendered = false;
}
- PageManager::NotifyKeyboard(KEYBOARD_SWIPE_LEFT);
+ PageManager::NotifyCharInput(KEYBOARD_SWIPE_LEFT);
return 0;
} else if (x > startX + (mRenderW * 0.5)) {
if (highlightRenderCount != 0) {
highlightRenderCount = 0;
mRendered = false;
}
- PageManager::NotifyKeyboard(KEYBOARD_SWIPE_RIGHT);
+ PageManager::NotifyCharInput(KEYBOARD_SWIPE_RIGHT);
return 0;
}
// fall through
@@ -520,10 +547,11 @@ int GUIKeyboard::NotifyTouch(TOUCH_STATE state, int x, int y)
return 0;
} else {
Key& key = *currentKey;
+ bool repeatKey = false;
Layout& lay = layouts[currentLayout - 1];
if (state == TOUCH_RELEASE && was_held == 0) {
DataManager::Vibrate("tw_keyboard_vibrate");
- if ((int)key.key == KEYBOARD_LAYOUT) {
+ if (key.layout > 0) {
// Switch layouts
if (lay.is_caps && key.layout == lay.revert_layout && !CapsLockOn) {
CapsLockOn = true; // Set the caps lock
@@ -532,14 +560,30 @@ int GUIKeyboard::NotifyTouch(TOUCH_STATE state, int x, int y)
currentLayout = key.layout;
}
mRendered = false;
- } else if ((int)key.key == KEYBOARD_ACTION) {
+ } else if (key.key == KEYBOARD_ACTION) {
// Action
highlightRenderCount = 0;
// Send action notification
- PageManager::NotifyKeyboard(key.key);
- } else if ((int)key.key < KEYBOARD_SPECIAL_KEYS && (int)key.key > 0) {
+ PageManager::NotifyCharInput(key.key);
+ } else if (key.key == -KEY_LEFTCTRL) {
+ CtrlActive = !CtrlActive; // toggle Control key state
+ mRendered = false; // render Ctrl key highlight
+ } else if (key.key != 0) {
// Regular key
- PageManager::NotifyKeyboard(key.key);
+ if (key.key > 0) {
+ // ASCII code or character
+ int keycode = key.key;
+ if (CtrlActive) {
+ CtrlActive = false;
+ mRendered = false;
+ keycode = KeyCharToCtrlChar(key.key);
+ }
+ PageManager::NotifyCharInput(keycode);
+ } else {
+ // Linux key code
+ PageManager::NotifyKey(-key.key, true);
+ PageManager::NotifyKey(-key.key, false);
+ }
if (!CapsLockOn && lay.is_caps) {
// caps lock was not set, change layouts
currentLayout = lay.revert_layout;
@@ -548,19 +592,32 @@ int GUIKeyboard::NotifyTouch(TOUCH_STATE state, int x, int y)
}
} else if (state == TOUCH_HOLD) {
was_held = 1;
- if ((int)key.key == KEYBOARD_BACKSPACE) {
- // Repeat backspace
- PageManager::NotifyKeyboard(key.key);
- } else if ((int)key.longpresskey < KEYBOARD_SPECIAL_KEYS && (int)key.longpresskey > 0) {
+ if (key.longpresskey > 0) {
// Long Press Key
DataManager::Vibrate("tw_keyboard_vibrate");
- PageManager::NotifyKeyboard(key.longpresskey);
+ PageManager::NotifyCharInput(key.longpresskey);
}
+ else
+ repeatKey = true;
} else if (state == TOUCH_REPEAT) {
was_held = 1;
- if ((int)key.key == KEYBOARD_BACKSPACE) {
+ repeatKey = true;
+ }
+ if (repeatKey) {
+ if (key.key == KEYBOARD_BACKSPACE) {
// Repeat backspace
- PageManager::NotifyKeyboard(key.key);
+ PageManager::NotifyCharInput(key.key);
+ }
+ switch (key.key)
+ {
+ // Repeat arrows
+ case -KEY_LEFT:
+ case -KEY_RIGHT:
+ case -KEY_UP:
+ case -KEY_DOWN:
+ PageManager::NotifyKey(-key.key, true);
+ PageManager::NotifyKey(-key.key, false);
+ break;
}
}
}
@@ -569,3 +626,9 @@ int GUIKeyboard::NotifyTouch(TOUCH_STATE state, int x, int y)
return 0;
}
+
+void GUIKeyboard::SetPageFocus(int inFocus)
+{
+ if (inFocus)
+ CtrlActive = false;
+}