Merge "Revert "Force sync files written by minzip."" into android-5.1
diff --git a/gui/devices/1920x1200/res/ui.xml b/gui/devices/1920x1200/res/ui.xml
index 986c026..cac0279 100644
--- a/gui/devices/1920x1200/res/ui.xml
+++ b/gui/devices/1920x1200/res/ui.xml
@@ -427,14 +427,14 @@
 					<row1 key01="153:" key02="q" long02="1" key03="w" long03="2" key04="e" long04="3" key05="r" long05="4" key06="t" long06="5" key07="y" long07="6" key08="u" long08="7" key09="i" long09="8" key10="o" long10="9" key11="p" long11="0" key12="177:c:8" />
 					<row2 key01="213:layout3" key02="156:a" key03="156:s" key04="156:d" key05="156:f" key06="156:g" key07="156:h" key08="156:j" key09="k" key10="156:l" key11="303:action" />
 					<row3 key01="269:layout2" key02="154:z" key03="154:x" key04="154:c" key05="154:v" key06="154:b" key07="154:n" key08="154:m" key09="154:," long09="!" key10="154:." long10="?" key11="265:layout2" />
-					<row4 key01="600:" key02="720: " key03="/" long03=":" key04="-" long0="_" />
+					<row4 key01="600:" key02="720: " key03="/" long03=":" key04="-" long04="_" />
 				</layout1>
 				<layout2>
 					<keysize height="129" width="159" capslock="0" revert_layout="1" />
 					<row1 key01="153:" key02="Q" long02="1" key03="W" long03="2" key04="E" long04="3" key05="R" long05="4" key06="T" long06="5" key07="Y" long07="6" key08="U" long08="7" key09="I" long09="8" key10="O" long10="9" key11="P" long11="0" key12="177:c:8" />
 					<row2 key01="213:layout3" key02="156:A" key03="156:S" key04="156:D" key05="156:F" key06="156:G" key07="156:H" key08="156:J" key09="156:K" key10="156:L" key11="303:action" />
-					<row3 key01="269:layout1" key02="154:Z" key03="154:X" key04="154:C" key05="154:V" key06="154:B" key07="154:N" key08="154:M" key09="154:," long09="!" key10="154:." long10="?" key11="265:layout1" />
-					<row4 key01="600:" key02="720: " key03="/" long03=":" key04="-" long0="_" />
+					<row3 key01="269:layout1" key02="154:Z" key03="154:X" key04="154:C" key05="154:V" key06="154:B" key07="154:N" key08="154:M" key09="154:!" key10="154:?" key11="265:layout1" />
+					<row4 key01="600:" key02="720: " key03=":" key04="_" />
 				</layout2>
 				<layout3>
 					<keysize height="129" width="159" />
diff --git a/gui/keyboard.cpp b/gui/keyboard.cpp
index d0262aa..914c944 100644
--- a/gui/keyboard.cpp
+++ b/gui/keyboard.cpp
@@ -16,20 +16,8 @@
         along with TWRP.  If not, see <http://www.gnu.org/licenses/>.
 */
 
-#include <stdarg.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <fcntl.h>
-#include <sys/reboot.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <time.h>
-#include <unistd.h>
-#include <stdlib.h>
 #include "../data.hpp"
 
 #include <string>
@@ -56,26 +44,23 @@
 	xml_node<>* keylayout;
 	xml_node<>* keyrow;
 
-	for (layoutindex=0; layoutindex<MAX_KEYBOARD_LAYOUTS; layoutindex++)
-		keyboardImg[layoutindex] = NULL;
+	for (layoutindex=0; layoutindex<MAX_KEYBOARD_LAYOUTS; layoutindex++) {
+		layouts[layoutindex].keyboardImg = NULL;
+		memset(layouts[layoutindex].keys, 0, sizeof(Layout::keys));
+		memset(layouts[layoutindex].row_end_y, 0, sizeof(Layout::row_end_y));
+	}
 
 	mRendered = false;
 	currentLayout = 1;
-	mAction = NULL;
+	CapsLockOn = false;
 	KeyboardHeight = KeyboardWidth = 0;
 
 	if (!node)  return;
 
-	// Load the action
-	child = FindNode(node, "action");
-	if (child)
-	{
-		mAction = new GUIAction(node);
-	}
-
 	mHighlightColor = LoadAttrColor(FindNode(node, "highlight"), "color", &hasHighlight);
 	mCapsHighlightColor = LoadAttrColor(FindNode(node, "capshighlight"), "color", &hasCapsHighlight);
 
+	// compatibility ugliness: resources should be specified in the layouts themselves instead
 	// Load the images for the different layouts
 	child = FindNode(node, "layout");
 	if (child)
@@ -84,7 +69,7 @@
 		strcpy(resource, "resource1");
 		attr = child->first_attribute(resource);
 		while (attr && layoutindex < (MAX_KEYBOARD_LAYOUTS + 1)) {
-			keyboardImg[layoutindex - 1] = LoadAttrImage(child, resource);
+			layouts[layoutindex - 1].keyboardImg = LoadAttrImage(child, resource);
 
 			layoutindex++;
 			resource[8] = (char)(layoutindex + 48);
@@ -93,10 +78,10 @@
 	}
 
 	// Check the first image to get height and width
-	if (keyboardImg[0] && keyboardImg[0]->GetResource())
+	if (layouts[0].keyboardImg && layouts[0].keyboardImg->GetResource())
 	{
-		KeyboardWidth = keyboardImg[0]->GetWidth();
-		KeyboardHeight = keyboardImg[0]->GetHeight();
+		KeyboardWidth = layouts[0].keyboardImg->GetWidth();
+		KeyboardHeight = layouts[0].keyboardImg->GetHeight();
 	}
 
 	// Load all of the layout maps
@@ -110,29 +95,15 @@
 			return;
 		}
 
+		Layout& lay = layouts[layoutindex - 1];
+
 		child = keylayout->first_node("keysize");
-		if (child) {
-			attr = child->first_attribute("height");
-			if (attr)
-				keyHeight = scale_theme_y(atoi(attr->value()));
-			else
-				keyHeight = 0;
-			attr = child->first_attribute("width");
-			if (attr)
-				keyWidth = scale_theme_x(atoi(attr->value()));
-			else
-				keyWidth = 0;
-			attr = child->first_attribute("capslock");
-			if (attr)
-				caps_tracking[layoutindex - 1].capslock = atoi(attr->value());
-			else
-				caps_tracking[layoutindex - 1].capslock = 1;
-			attr = child->first_attribute("revert_layout");
-			if (attr)
-				caps_tracking[layoutindex - 1].revert_layout = atoi(attr->value());
-			else
-				caps_tracking[layoutindex - 1].revert_layout = -1;
-		}
+		keyHeight = LoadAttrIntScaleY(child, "height", 0);
+		keyWidth = LoadAttrIntScaleX(child, "width", 0);
+		// compatibility ugliness: capslock="0" means that this is the caps layout. Also it has nothing to do with keysize.
+		lay.is_caps = (LoadAttrInt(child, "capslock", 1) == 0);
+		// compatibility ugliness: revert_layout has nothing to do with keysize.
+		lay.revert_layout = LoadAttrInt(child, "revert_layout", -1);
 
 		rowindex = 1;
 		Yindex = 0;
@@ -146,7 +117,7 @@
 			}
 
 			Yindex += keyHeight;
-			row_heights[layoutindex - 1][rowindex - 1] = Yindex;
+			lay.row_end_y[rowindex - 1] = Yindex;
 
 			keyindex = 1;
 			Xindex = 0;
@@ -166,7 +137,7 @@
 					return;
 				}
 
-				if (ParseKey(keyinfo, keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1], Xindex, keyWidth, false))
+				if (ParseKey(keyinfo, lay.keys[rowindex - 1][keyindex - 1], Xindex, keyWidth, false))
 					LOGERR("Invalid key info on layout%i, row%i, key%02i.\n", layoutindex, rowindex, keyindex);
 
 
@@ -181,7 +152,7 @@
 						return;
 					}
 
-					if (ParseKey(keyinfo, keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1], Xindex, keyWidth, true))
+					if (ParseKey(keyinfo, lay.keys[rowindex - 1][keyindex - 1], Xindex, keyWidth, true))
 						LOGERR("Invalid long press key info on layout%i, row%i, long%02i.\n", layoutindex, rowindex, keyindex);
 				}
 				keyindex++;
@@ -197,11 +168,10 @@
 		keylayout = FindNode(node, layout);
 	}
 
-	int x, y, w, h;
+	int x, y;
 	// Load the placement
-	LoadPlacement(FindNode(node, "placement"), &x, &y, &w, &h);
-	SetActionPos(x, y, KeyboardWidth, KeyboardHeight);
-	SetRenderPos(x, y, w, h);
+	LoadPlacement(FindNode(node, "placement"), &x, &y);
+	SetRenderPos(x, y, KeyboardWidth, KeyboardHeight);
 	return;
 }
 
@@ -209,7 +179,7 @@
 {
 }
 
-int GUIKeyboard::ParseKey(const char* keyinfo, keyboard_key_class& key, int& Xindex, int keyWidth, bool longpress)
+int GUIKeyboard::ParseKey(const char* keyinfo, Key& key, int& Xindex, int keyWidth, bool longpress)
 {
 	int keychar = 0;
 	if (strlen(keyinfo) == 1) {
@@ -260,30 +230,30 @@
 		return 0;
 	}
 
-	int ret = 0;
+	Layout& lay = layouts[currentLayout - 1];
 
-	if (keyboardImg[currentLayout - 1] && keyboardImg[currentLayout - 1]->GetResource())
-		gr_blit(keyboardImg[currentLayout - 1]->GetResource(), 0, 0, KeyboardWidth, KeyboardHeight, mRenderX, mRenderY);
+	if (lay.keyboardImg && lay.keyboardImg->GetResource())
+		gr_blit(lay.keyboardImg->GetResource(), 0, 0, KeyboardWidth, KeyboardHeight, mRenderX, mRenderY);
 
 	// Draw highlight for capslock
-	if (hasCapsHighlight && caps_tracking[currentLayout - 1].capslock == 0 && caps_tracking[currentLayout - 1].set_capslock) {
-		int boxheight, boxwidth, x;
+	if (hasCapsHighlight && lay.is_caps && CapsLockOn) {
 		gr_color(mCapsHighlightColor.red, mCapsHighlightColor.green, mCapsHighlightColor.blue, mCapsHighlightColor.alpha);
 		for (int indexy=0; indexy<MAX_KEYBOARD_ROWS; indexy++) {
 			for (int indexx=0; indexx<MAX_KEYBOARD_KEYS; indexx++) {
-				if ((int)keyboard_keys[currentLayout - 1][indexy][indexx].key == KEYBOARD_LAYOUT && (int)keyboard_keys[currentLayout - 1][indexy][indexx].layout == caps_tracking[currentLayout - 1].revert_layout) {
+				if ((int)lay.keys[indexy][indexx].key == KEYBOARD_LAYOUT && (int)lay.keys[indexy][indexx].layout == lay.revert_layout) {
+					int boxheight, boxwidth, x;
 					if (indexy == 0)
-						boxheight = row_heights[currentLayout - 1][indexy];
+						boxheight = lay.row_end_y[indexy];
 					else
-						boxheight = row_heights[currentLayout - 1][indexy] - row_heights[currentLayout - 1][indexy - 1];
+						boxheight = lay.row_end_y[indexy] - lay.row_end_y[indexy - 1];
 					if (indexx == 0) {
 						x = mRenderX;
-						boxwidth = keyboard_keys[currentLayout - 1][indexy][indexx].end_x;
+						boxwidth = lay.keys[indexy][indexx].end_x;
 					} else {
-						x = mRenderX + keyboard_keys[currentLayout - 1][indexy][indexx - 1].end_x;
-						boxwidth = keyboard_keys[currentLayout - 1][indexy][indexx].end_x - keyboard_keys[currentLayout - 1][indexy][indexx - 1].end_x;
+						x = mRenderX + lay.keys[indexy][indexx - 1].end_x;
+						boxwidth = lay.keys[indexy][indexx].end_x - lay.keys[indexy][indexx - 1].end_x;
 					}
-					gr_fill(x, mRenderY + row_heights[currentLayout - 1][indexy - 1], boxwidth, boxheight);
+					gr_fill(x, mRenderY + lay.row_end_y[indexy - 1], boxwidth, boxheight);
 				}
 			}
 		}
@@ -292,24 +262,24 @@
 	if (hasHighlight && highlightRenderCount != 0) {
 		int boxheight, boxwidth, x;
 		if (rowY == 0)
-			boxheight = row_heights[currentLayout - 1][rowY];
+			boxheight = lay.row_end_y[rowY];
 		else
-			boxheight = row_heights[currentLayout - 1][rowY] - row_heights[currentLayout - 1][rowY - 1];
+			boxheight = lay.row_end_y[rowY] - lay.row_end_y[rowY - 1];
 		if (colX == 0) {
 			x = mRenderX;
-			boxwidth = keyboard_keys[currentLayout - 1][rowY][colX].end_x;
+			boxwidth = lay.keys[rowY][colX].end_x;
 		} else {
-			x = mRenderX + keyboard_keys[currentLayout - 1][rowY][colX - 1].end_x;
-			boxwidth = keyboard_keys[currentLayout - 1][rowY][colX].end_x - keyboard_keys[currentLayout - 1][rowY][colX - 1].end_x;
+			x = mRenderX + lay.keys[rowY][colX - 1].end_x;
+			boxwidth = lay.keys[rowY][colX].end_x - lay.keys[rowY][colX - 1].end_x;
 		}
 		gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, mHighlightColor.alpha);
-		gr_fill(x, mRenderY + row_heights[currentLayout - 1][rowY - 1], boxwidth, boxheight);
+		gr_fill(x, mRenderY + lay.row_end_y[rowY - 1], boxwidth, boxheight);
 		if (highlightRenderCount > 0)
 			highlightRenderCount--;
 	} else
 		mRendered = true;
 
-	return ret;
+	return 0;
 }
 
 int GUIKeyboard::Update(void)
@@ -324,73 +294,70 @@
 {
 	mRenderX = x;
 	mRenderY = y;
-	if (w || h)
-	{
-		mRenderW = KeyboardWidth;
-		mRenderH = KeyboardHeight;
-	}
-
-	if (mAction)		mAction->SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
+	mRenderW = KeyboardWidth;
+	mRenderH = KeyboardHeight;
 	SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
 	return 0;
 }
 
-int GUIKeyboard::GetSelection(int x, int y)
+GUIKeyboard::Key* GUIKeyboard::HitTestKey(int x, int y)
 {
-	if (x < mRenderX || x - mRenderX > (int)KeyboardWidth || y < mRenderY || y - mRenderY > (int)KeyboardHeight) return -1;
-	return 0;
+	if (!IsInRegion(x, y))
+		return NULL;
+
+	int rely = y - mRenderY;
+	int relx = x - mRenderX;
+
+	Layout& lay = layouts[currentLayout - 1];
+
+	// Find the correct row
+	int row;
+	for (row = 0; row < MAX_KEYBOARD_ROWS; ++row) {
+		if (lay.row_end_y[row] > rely)
+			break;
+	}
+	if (row == MAX_KEYBOARD_ROWS)
+		return NULL;
+
+	// Find the correct key (column)
+	int col;
+	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) {
+			// This is the key that was pressed!
+			rowY = row;
+			colX = col;
+			return &key;
+		}
+		x1 = key.end_x;
+	}
+	return NULL;
 }
 
 int GUIKeyboard::NotifyTouch(TOUCH_STATE state, int x, int y)
 {
-	static int startSelection = -1, was_held = 0, startX = 0;
-	static unsigned char initial_key = 0;
-	int indexy, indexx, rely, relx, rowIndex = 0;
-
-	rely = y - mRenderY;
-	relx = x - mRenderX;
+	static int was_held = 0, startX = 0;
+	static Key* initial_key = 0;
 
 	if (!isConditionTrue())	 return -1;
 
 	switch (state)
 	{
 	case TOUCH_START:
-		if (GetSelection(x, y) == 0) {
-			startSelection = -1;
-			was_held = 0;
-			startX = x;
-			// Find the correct row
-			for (indexy=0; indexy<MAX_KEYBOARD_ROWS; indexy++) {
-				if (row_heights[currentLayout - 1][indexy] > rely) {
-					rowIndex = indexy;
-					rowY = indexy;
-					indexy = MAX_KEYBOARD_ROWS;
-				}
-			}
-
-			// Find the correct key (column)
-			for (indexx=0; indexx<MAX_KEYBOARD_KEYS; indexx++) {
-				if (keyboard_keys[currentLayout - 1][rowIndex][indexx].end_x > relx) {
-					// This is the key that was pressed!
-					initial_key = keyboard_keys[currentLayout - 1][rowIndex][indexx].key;
-					colX = indexx;
-					indexx = MAX_KEYBOARD_KEYS;
-				}
-			}
-			if (initial_key != 0)
-				highlightRenderCount = -1;
-			else
-				highlightRenderCount = 0;
-			mRendered = false;
-		} else {
-			if (highlightRenderCount != 0)
-				mRendered = false;
+		was_held = 0;
+		startX = x;
+		initial_key = HitTestKey(x, y);
+		if (initial_key)
+			highlightRenderCount = -1;
+		else
 			highlightRenderCount = 0;
-			startSelection = 0;
-		}
+		mRendered = false;
 		break;
+
 	case TOUCH_DRAG:
 		break;
+
 	case TOUCH_RELEASE:
 		if (x < startX - (KeyboardWidth * 0.5)) {
 			if (highlightRenderCount != 0) {
@@ -407,17 +374,18 @@
 			PageManager::NotifyKeyboard(KEYBOARD_SWIPE_RIGHT);
 			return 0;
 		}
-
+		// fall through
 	case TOUCH_HOLD:
 	case TOUCH_REPEAT:
-
-		if (startSelection == 0 || GetSelection(x, y) == -1) {
+		if (!initial_key) {
 			if (highlightRenderCount != 0) {
 				highlightRenderCount = 0;
 				mRendered = false;
 			}
 			return 0;
-		} else if (highlightRenderCount != 0) {
+		}
+
+		if (highlightRenderCount != 0) {
 			if (state == TOUCH_RELEASE)
 				highlightRenderCount = 2;
 			else
@@ -425,75 +393,57 @@
 			mRendered = false;
 		}
 
-		// Find the correct row
-		for (indexy=0; indexy<MAX_KEYBOARD_ROWS; indexy++) {
-			if (row_heights[currentLayout - 1][indexy] > rely) {
-				rowIndex = indexy;
-				indexy = MAX_KEYBOARD_ROWS;
+		if (HitTestKey(x, y) != initial_key) {
+			// We dragged off of the starting key
+			if (highlightRenderCount != 0) {
+				highlightRenderCount = 0;
+				mRendered = false;
 			}
-		}
-
-		// Find the correct key (column)
-		for (indexx=0; indexx<MAX_KEYBOARD_KEYS; indexx++) {
-			keyboard_key_class& key = keyboard_keys[currentLayout - 1][rowIndex][indexx];
-			if (key.end_x > relx) {
-				// This is the key that was pressed!
-				if (key.key != initial_key) {
-					// We dragged off of the starting key
-					startSelection = 0;
-					break;
-				} else if (state == TOUCH_RELEASE && was_held == 0) {
-					DataManager::Vibrate("tw_keyboard_vibrate");
-					if ((int)key.key < KEYBOARD_SPECIAL_KEYS && (int)key.key > 0) {
-						// Regular key
-						PageManager::NotifyKeyboard(key.key);
-						if (caps_tracking[currentLayout - 1].capslock == 0 && !caps_tracking[currentLayout - 1].set_capslock) {
-							// caps lock was not set, change layouts
-							currentLayout = caps_tracking[currentLayout - 1].revert_layout;
-							mRendered = false;
-						}
-					} else if ((int)key.key == KEYBOARD_LAYOUT) {
-						// Switch layouts
-						if (caps_tracking[currentLayout - 1].capslock == 0 && key.layout == caps_tracking[currentLayout - 1].revert_layout) {
-							if (!caps_tracking[currentLayout - 1].set_capslock) {
-								caps_tracking[currentLayout - 1].set_capslock = 1; // Set the caps lock
-							} else {
-								caps_tracking[currentLayout - 1].set_capslock = 0; // Unset the caps lock and change layouts
-								currentLayout = key.layout;
-							}
-						} else {
-							currentLayout = key.layout;
-						}
+			return 0;
+		} else {
+			Key& key = *initial_key;
+			Layout& lay = layouts[currentLayout - 1];
+			if (state == TOUCH_RELEASE && was_held == 0) {
+				DataManager::Vibrate("tw_keyboard_vibrate");
+				if ((int)key.key == KEYBOARD_LAYOUT) {
+					// Switch layouts
+					if (lay.is_caps && key.layout == lay.revert_layout && !CapsLockOn) {
+						CapsLockOn = true; // Set the caps lock
+					} else {
+						CapsLockOn = false; // Unset the caps lock and change layouts
+						currentLayout = key.layout;
+					}
+					mRendered = false;
+				} else if ((int)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) {
+					// Regular key
+					PageManager::NotifyKeyboard(key.key);
+					if (!CapsLockOn && lay.is_caps) {
+						// caps lock was not set, change layouts
+						currentLayout = lay.revert_layout;
 						mRendered = false;
-					} else if ((int)key.key == KEYBOARD_ACTION) {
-						// Action
-						highlightRenderCount = 0;
-						if (mAction) {
-							// Keyboard has its own action defined
-							return (mAction ? mAction->NotifyTouch(state, x, y) : 1);
-						} else {
-							// Send action notification
-							PageManager::NotifyKeyboard(key.key);
-						}
-					}
-				} 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) {
-						// Long Press Key
-						DataManager::Vibrate("tw_keyboard_vibrate");
-						PageManager::NotifyKeyboard(key.longpresskey);
-					}
-				} else if (state == TOUCH_REPEAT) {
-					was_held = 1;
-					if ((int)key.key == KEYBOARD_BACKSPACE) {
-						// Repeat backspace
-						PageManager::NotifyKeyboard(key.key);
 					}
 				}
-				indexx = MAX_KEYBOARD_KEYS;
+			} 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) {
+					// Long Press Key
+					DataManager::Vibrate("tw_keyboard_vibrate");
+					PageManager::NotifyKeyboard(key.longpresskey);
+				}
+			} else if (state == TOUCH_REPEAT) {
+				was_held = 1;
+				if ((int)key.key == KEYBOARD_BACKSPACE) {
+					// Repeat backspace
+					PageManager::NotifyKeyboard(key.key);
+				}
 			}
 		}
 		break;
diff --git a/gui/objects.hpp b/gui/objects.hpp
index d26b0c2..e70053e 100644
--- a/gui/objects.hpp
+++ b/gui/objects.hpp
@@ -815,9 +815,6 @@
 	int sUpdate;
 };
 
-#define MAX_KEYBOARD_LAYOUTS 5
-#define MAX_KEYBOARD_ROWS 9
-#define MAX_KEYBOARD_KEYS 20
 #define KEYBOARD_ACTION 253
 #define KEYBOARD_LAYOUT 254
 #define KEYBOARD_SWIPE_LEFT 252
@@ -844,35 +841,40 @@
 	virtual int SetRenderPos(int x, int y, int w = 0, int h = 0);
 
 protected:
-	virtual int GetSelection(int x, int y);
-
-protected:
-	struct keyboard_key_class
+	struct Key
 	{
-		unsigned char key;
+		unsigned char key; // ASCII code or one of the special KEYBOARD_* codes above
 		unsigned char longpresskey;
 		int end_x;
 		int layout;
 	};
-	int ParseKey(const char* keyinfo, keyboard_key_class& key, int& Xindex, int keyWidth, bool longpress);
-	struct capslock_tracking_struct
+	int ParseKey(const char* keyinfo, Key& key, int& Xindex, int keyWidth, bool longpress);
+
+	enum {
+		MAX_KEYBOARD_LAYOUTS = 5,
+		MAX_KEYBOARD_ROWS = 9,
+		MAX_KEYBOARD_KEYS = 20
+	};
+	struct Layout
 	{
-		int capslock;
-		int set_capslock;
+		ImageResource* keyboardImg;
+		struct Key keys[MAX_KEYBOARD_ROWS][MAX_KEYBOARD_KEYS];
+		int row_end_y[MAX_KEYBOARD_ROWS];
+		bool is_caps;
 		int revert_layout;
 	};
+	Layout layouts[MAX_KEYBOARD_LAYOUTS];
 
-	ImageResource* keyboardImg[MAX_KEYBOARD_LAYOUTS];
-	struct keyboard_key_class keyboard_keys[MAX_KEYBOARD_LAYOUTS][MAX_KEYBOARD_ROWS][MAX_KEYBOARD_KEYS];
-	struct capslock_tracking_struct caps_tracking[MAX_KEYBOARD_LAYOUTS];
+	// Find key at screen coordinates
+	Key* HitTestKey(int x, int y);
+
 	bool mRendered;
 	std::string mVariable;
 	int currentLayout;
-	int row_heights[MAX_KEYBOARD_LAYOUTS][MAX_KEYBOARD_ROWS];
+	bool CapsLockOn;
 	unsigned int KeyboardWidth, KeyboardHeight;
 	int rowY, colX, highlightRenderCount;
 	bool hasHighlight, hasCapsHighlight;
-	GUIAction* mAction;
 	COLOR mHighlightColor;
 	COLOR mCapsHighlightColor;
 };