blob: e55fb1b6611853c2de868ffe9a3d024387d079aa [file] [log] [blame]
Dees Troy3be70a82013-10-22 14:25:12 +00001/*
2 Copyright 2012 bigbiff/Dees_Troy TeamWin
3 This file is part of TWRP/TeamWin Recovery Project.
4
5 TWRP is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 TWRP is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
17*/
Dees_Troy51a0e822012-09-05 15:24:24 -040018
Dees_Troy51a0e822012-09-05 15:24:24 -040019#include <stdlib.h>
20#include <string.h>
Samer Diab (S.a.M.e.R_d)71e9b042014-01-07 20:18:47 +000021#include "../data.hpp"
Dees_Troy51a0e822012-09-05 15:24:24 -040022
23#include <string>
24
25extern "C" {
Dees_Troy2673cec2013-04-02 20:22:16 +000026#include "../twcommon.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040027#include "../minuitwrp/minui.h"
Ethan Yonker63e414f2015-02-06 15:44:39 -060028#include "gui.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040029}
30
31#include "rapidxml.hpp"
32#include "objects.hpp"
33
34GUIKeyboard::GUIKeyboard(xml_node<>* node)
Vojtech Bocekede51c52014-02-07 23:58:09 +010035 : GUIObject(node)
Dees_Troy51a0e822012-09-05 15:24:24 -040036{
37 int layoutindex, rowindex, keyindex, Xindex, Yindex, keyHeight = 0, keyWidth = 0;
thatf6b20662015-06-25 21:51:37 +020038 currentKey = NULL;
Ethan Yonker21ff02a2015-02-18 14:35:00 -060039 highlightRenderCount = 0;
40 hasHighlight = hasCapsHighlight = false;
Dees_Troy3a16cb52013-01-10 15:16:02 +000041 char resource[10], layout[8], row[5], key[6], longpress[7];
Dees_Troy51a0e822012-09-05 15:24:24 -040042 xml_attribute<>* attr;
43 xml_node<>* child;
44 xml_node<>* keylayout;
45 xml_node<>* keyrow;
46
thatd86f49d2015-03-15 00:56:57 +010047 for (layoutindex=0; layoutindex<MAX_KEYBOARD_LAYOUTS; layoutindex++) {
48 layouts[layoutindex].keyboardImg = NULL;
49 memset(layouts[layoutindex].keys, 0, sizeof(Layout::keys));
50 memset(layouts[layoutindex].row_end_y, 0, sizeof(Layout::row_end_y));
51 }
Dees_Troy51a0e822012-09-05 15:24:24 -040052
53 mRendered = false;
54 currentLayout = 1;
thatd86f49d2015-03-15 00:56:57 +010055 CapsLockOn = false;
Dees_Troy51a0e822012-09-05 15:24:24 -040056
57 if (!node) return;
58
Ethan Yonker21ff02a2015-02-18 14:35:00 -060059 mHighlightColor = LoadAttrColor(FindNode(node, "highlight"), "color", &hasHighlight);
60 mCapsHighlightColor = LoadAttrColor(FindNode(node, "capshighlight"), "color", &hasCapsHighlight);
Ethan Yonkerc3120d42014-02-17 07:55:00 -060061
thatf256b722015-05-23 20:44:12 +020062 child = FindNode(node, "keymargin");
63 mKeyMarginX = LoadAttrIntScaleX(child, "x", 0);
64 mKeyMarginY = LoadAttrIntScaleY(child, "y", 0);
65
66 child = FindNode(node, "background");
67 mBackgroundColor = LoadAttrColor(child, "color", COLOR(32,32,32,255));
68
69 child = FindNode(node, "key-alphanumeric");
70 mFont = PageManager::GetResources()->FindFont(LoadAttrString(child, "font", "keylabel"));
71 mFontColor = LoadAttrColor(child, "textcolor", COLOR(255,255,255,255));
72 mKeyColorAlphanumeric = LoadAttrColor(child, "color", COLOR(0,0,0,0));
73
74 child = FindNode(node, "key-other");
75 mSmallFont = PageManager::GetResources()->FindFont(LoadAttrString(child, "font", "keylabel-small"));
76 mFontColorSmall = LoadAttrColor(child, "textcolor", COLOR(192,192,192,255));
77 mKeyColorOther = LoadAttrColor(child, "color", COLOR(0,0,0,0));
78
79 child = FindNode(node, "longpress");
80 mLongpressFont = PageManager::GetResources()->FindFont(LoadAttrString(child, "font", "keylabel-longpress"));
81 mLongpressFontColor = LoadAttrColor(child, "textcolor", COLOR(128,128,128,255));
thatf6b20662015-06-25 21:51:37 +020082 LoadPlacement(child, &longpressOffsetX, &longpressOffsetY);
thatf256b722015-05-23 20:44:12 +020083
84 LoadKeyLabels(node, 0); // load global key labels
85
thatd86f49d2015-03-15 00:56:57 +010086 // compatibility ugliness: resources should be specified in the layouts themselves instead
Dees_Troy51a0e822012-09-05 15:24:24 -040087 // Load the images for the different layouts
Ethan Yonker21ff02a2015-02-18 14:35:00 -060088 child = FindNode(node, "layout");
Dees_Troy51a0e822012-09-05 15:24:24 -040089 if (child)
90 {
91 layoutindex = 1;
92 strcpy(resource, "resource1");
93 attr = child->first_attribute(resource);
94 while (attr && layoutindex < (MAX_KEYBOARD_LAYOUTS + 1)) {
thatd86f49d2015-03-15 00:56:57 +010095 layouts[layoutindex - 1].keyboardImg = LoadAttrImage(child, resource);
Dees_Troy51a0e822012-09-05 15:24:24 -040096
97 layoutindex++;
98 resource[8] = (char)(layoutindex + 48);
99 attr = child->first_attribute(resource);
100 }
101 }
102
103 // Check the first image to get height and width
thatd86f49d2015-03-15 00:56:57 +0100104 if (layouts[0].keyboardImg && layouts[0].keyboardImg->GetResource())
Dees_Troy51a0e822012-09-05 15:24:24 -0400105 {
thatf256b722015-05-23 20:44:12 +0200106 mRenderW = layouts[0].keyboardImg->GetWidth();
107 mRenderH = layouts[0].keyboardImg->GetHeight();
Dees_Troy51a0e822012-09-05 15:24:24 -0400108 }
109
110 // Load all of the layout maps
111 layoutindex = 1;
112 strcpy(layout, "layout1");
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600113 keylayout = FindNode(node, layout);
Dees_Troy51a0e822012-09-05 15:24:24 -0400114 while (keylayout)
115 {
116 if (layoutindex > MAX_KEYBOARD_LAYOUTS) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000117 LOGERR("Too many layouts defined in keyboard.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400118 return;
119 }
120
thatf256b722015-05-23 20:44:12 +0200121 LoadKeyLabels(keylayout, layoutindex); // load per-layout key labels
122
thatd86f49d2015-03-15 00:56:57 +0100123 Layout& lay = layouts[layoutindex - 1];
124
Dees_Troy51a0e822012-09-05 15:24:24 -0400125 child = keylayout->first_node("keysize");
thatd86f49d2015-03-15 00:56:57 +0100126 keyHeight = LoadAttrIntScaleY(child, "height", 0);
127 keyWidth = LoadAttrIntScaleX(child, "width", 0);
128 // compatibility ugliness: capslock="0" means that this is the caps layout. Also it has nothing to do with keysize.
129 lay.is_caps = (LoadAttrInt(child, "capslock", 1) == 0);
130 // compatibility ugliness: revert_layout has nothing to do with keysize.
131 lay.revert_layout = LoadAttrInt(child, "revert_layout", -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400132
133 rowindex = 1;
134 Yindex = 0;
135 strcpy(row, "row1");
136 keyrow = keylayout->first_node(row);
137 while (keyrow)
138 {
139 if (rowindex > MAX_KEYBOARD_ROWS) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000140 LOGERR("Too many rows defined in keyboard.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400141 return;
142 }
143
144 Yindex += keyHeight;
thatd86f49d2015-03-15 00:56:57 +0100145 lay.row_end_y[rowindex - 1] = Yindex;
Dees_Troy51a0e822012-09-05 15:24:24 -0400146
147 keyindex = 1;
148 Xindex = 0;
149 strcpy(key, "key01");
150 attr = keyrow->first_attribute(key);
151
152 while (attr) {
Dees_Troy51a0e822012-09-05 15:24:24 -0400153 if (keyindex > MAX_KEYBOARD_KEYS) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000154 LOGERR("Too many keys defined in a keyboard row.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400155 return;
156 }
157
that1a7ba972015-02-01 19:48:19 +0100158 const char* keyinfo = attr->value();
Dees_Troy51a0e822012-09-05 15:24:24 -0400159
160 if (strlen(keyinfo) == 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000161 LOGERR("No key info on layout%i, row%i, key%dd.\n", layoutindex, rowindex, keyindex);
Dees_Troy51a0e822012-09-05 15:24:24 -0400162 return;
163 }
164
thatd86f49d2015-03-15 00:56:57 +0100165 if (ParseKey(keyinfo, lay.keys[rowindex - 1][keyindex - 1], Xindex, keyWidth, false))
that1a7ba972015-02-01 19:48:19 +0100166 LOGERR("Invalid key info on layout%i, row%i, key%02i.\n", layoutindex, rowindex, keyindex);
Dees_Troy51a0e822012-09-05 15:24:24 -0400167
Dees_Troy51a0e822012-09-05 15:24:24 -0400168
169 // PROCESS LONG PRESS INFO IF EXISTS
170 sprintf(longpress, "long%02i", keyindex);
171 attr = keyrow->first_attribute(longpress);
172 if (attr) {
that1a7ba972015-02-01 19:48:19 +0100173 const char* keyinfo = attr->value();
Dees_Troy51a0e822012-09-05 15:24:24 -0400174
175 if (strlen(keyinfo) == 0) {
Dees_Troy2673cec2013-04-02 20:22:16 +0000176 LOGERR("No long press info on layout%i, row%i, long%dd.\n", layoutindex, rowindex, keyindex);
Dees_Troy51a0e822012-09-05 15:24:24 -0400177 return;
178 }
179
thatd86f49d2015-03-15 00:56:57 +0100180 if (ParseKey(keyinfo, lay.keys[rowindex - 1][keyindex - 1], Xindex, keyWidth, true))
that1a7ba972015-02-01 19:48:19 +0100181 LOGERR("Invalid long press key info on layout%i, row%i, long%02i.\n", layoutindex, rowindex, keyindex);
Dees_Troy51a0e822012-09-05 15:24:24 -0400182 }
183 keyindex++;
184 sprintf(key, "key%02i", keyindex);
185 attr = keyrow->first_attribute(key);
186 }
187 rowindex++;
188 row[3] = (char)(rowindex + 48);
189 keyrow = keylayout->first_node(row);
190 }
191 layoutindex++;
192 layout[6] = (char)(layoutindex + 48);
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600193 keylayout = FindNode(node, layout);
Dees_Troy51a0e822012-09-05 15:24:24 -0400194 }
195
thate79878b2015-03-14 23:07:23 +0100196 int x, y;
Dees_Troy51a0e822012-09-05 15:24:24 -0400197 // Load the placement
thatf256b722015-05-23 20:44:12 +0200198 LoadPlacement(FindNode(node, "placement"), &x, &y, &mRenderW, &mRenderH);
199 SetRenderPos(x, y, mRenderW, mRenderH);
Dees_Troy51a0e822012-09-05 15:24:24 -0400200 return;
201}
202
203GUIKeyboard::~GUIKeyboard()
204{
that1a7ba972015-02-01 19:48:19 +0100205}
Dees_Troy51a0e822012-09-05 15:24:24 -0400206
thate79878b2015-03-14 23:07:23 +0100207int GUIKeyboard::ParseKey(const char* keyinfo, Key& key, int& Xindex, int keyWidth, bool longpress)
that1a7ba972015-02-01 19:48:19 +0100208{
thatf256b722015-05-23 20:44:12 +0200209 key.layout = 0;
that1a7ba972015-02-01 19:48:19 +0100210 int keychar = 0;
211 if (strlen(keyinfo) == 1) {
212 // This is a single key, simple definition
213 keychar = keyinfo[0];
214 } else {
215 // This key has extra data: {keywidth}:{what_the_key_does}
Ethan Yonker63e414f2015-02-06 15:44:39 -0600216 keyWidth = scale_theme_x(atoi(keyinfo));
that1a7ba972015-02-01 19:48:19 +0100217
218 const char* ptr = keyinfo;
219 while (*ptr > 32 && *ptr != ':')
220 ptr++;
221 if (*ptr != ':')
222 return -1; // no colon is an error
223 ptr++;
224
225 if (*ptr == 0) { // This is an empty area
226 keychar = 0;
227 } else if (strlen(ptr) == 1) { // This is the character that this key uses
228 keychar = *ptr;
229 } else if (*ptr == 'c') { // This is an ASCII character code: "c:{number}"
230 keychar = atoi(ptr + 2);
231 } else if (*ptr == 'l') { // This is a different layout: "layout{number}"
232 keychar = KEYBOARD_LAYOUT;
233 key.layout = atoi(ptr + 6);
234 } else if (*ptr == 'a') { // This is an action: "action"
235 keychar = KEYBOARD_ACTION;
236 } else
237 return -1;
238 }
239
240 if (longpress) {
241 key.longpresskey = keychar;
242 } else {
243 key.key = keychar;
244 Xindex += keyWidth;
245 key.end_x = Xindex - 1;
246 }
247
248 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400249}
250
thatf256b722015-05-23 20:44:12 +0200251void GUIKeyboard::LoadKeyLabels(xml_node<>* parent, int layout)
252{
253 for (xml_node<>* child = parent->first_node(); child; child = child->next_sibling()) {
254 std::string name = child->name();
255 if (name == "keylabel") {
256 std::string keydef = LoadAttrString(child, "key", "");
257 Key tempkey;
258 int dummyX;
259 if (ParseKey(keydef.c_str(), tempkey, dummyX, 0, false) == 0) {
260 KeyLabel keylabel;
261 keylabel.key = tempkey.key;
262 keylabel.layout_from = layout;
263 keylabel.layout_to = tempkey.layout;
264 keylabel.text = LoadAttrString(child, "text", "");
265 keylabel.image = LoadAttrImage(child, "resource");
266 mKeyLabels.push_back(keylabel);
267 } else {
268 LOGERR("Ignoring invalid keylabel in layout %d: '%s'.\n", layout, keydef.c_str());
269 }
270 }
271 }
272}
273
thatf6b20662015-06-25 21:51:37 +0200274void GUIKeyboard::DrawKey(Key& key, int keyX, int keyY, int keyW, int keyH)
275{
276 unsigned char keychar = key.key;
277 if (!keychar)
278 return;
279
280 // key background
281 COLOR& c = (keychar >= 32 && keychar < 127) ? mKeyColorAlphanumeric : mKeyColorOther;
282 gr_color(c.red, c.green, c.blue, c.alpha);
283 keyX += mKeyMarginX;
284 keyY += mKeyMarginY;
285 keyW -= mKeyMarginX * 2;
286 keyH -= mKeyMarginY * 2;
287 gr_fill(keyX, keyY, keyW, keyH);
288
289 // key label
290 FontResource* labelFont = mFont;
291 string labelText;
292 ImageResource* labelImage = NULL;
293 if (keychar > 32 && keychar < 127) {
294 labelText = (char) keychar;
295 gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, mFontColor.alpha);
296 }
297 else {
298 // search for a special key label
299 for (std::vector<KeyLabel>::iterator it = mKeyLabels.begin(); it != mKeyLabels.end(); ++it) {
300 if (it->layout_from > 0 && it->layout_from != currentLayout)
301 continue; // this label is for another layout
302 if (it->key == key.key && it->layout_to == key.layout)
303 {
304 // found a label
305 labelText = it->text;
306 labelImage = it->image;
307 break;
308 }
309 }
310 labelFont = mSmallFont;
311 gr_color(mFontColorSmall.red, mFontColorSmall.green, mFontColorSmall.blue, mFontColorSmall.alpha);
312 }
313
314 if (labelImage)
315 {
316 int w = labelImage->GetWidth();
317 int h = labelImage->GetHeight();
318 int x = keyX + (keyW - w) / 2;
319 int y = keyY + (keyH - h) / 2;
320 gr_blit(labelImage->GetResource(), 0, 0, w, h, x, y);
321 }
322 else if (!labelText.empty())
323 {
324 void* fontResource = labelFont->GetResource();
325 int textW = gr_measureEx(labelText.c_str(), fontResource);
326 int textH = labelFont->GetHeight();
327 int textX = keyX + (keyW - textW) / 2;
328 int textY = keyY + (keyH - textH) / 2;
Ethan Yonkerb7a54a32015-10-05 10:16:27 -0500329 gr_textEx_scaleW(textX, textY, labelText.c_str(), fontResource, keyW, TOP_LEFT, 0);
thatf6b20662015-06-25 21:51:37 +0200330 }
331
332 // longpress key label (only if font is defined)
333 keychar = key.longpresskey;
334 if (keychar > 32 && keychar < 127 && mLongpressFont->GetResource()) {
335 void* fontResource = mLongpressFont->GetResource();
336 gr_color(mLongpressFontColor.red, mLongpressFontColor.green, mLongpressFontColor.blue, mLongpressFontColor.alpha);
337 string text(1, keychar);
338 int textH = mLongpressFont->GetHeight();
339 int textW = gr_measureEx(text.c_str(), fontResource);
340 int textX = keyX + keyW - longpressOffsetX - textW;
341 int textY = keyY + longpressOffsetY;
Ethan Yonkerb7a54a32015-10-05 10:16:27 -0500342 gr_textEx_scaleW(textX, textY, text.c_str(), fontResource, keyW, TOP_LEFT, 0);
thatf6b20662015-06-25 21:51:37 +0200343 }
344}
345
Dees_Troy51a0e822012-09-05 15:24:24 -0400346int GUIKeyboard::Render(void)
347{
348 if (!isConditionTrue())
349 {
350 mRendered = false;
351 return 0;
352 }
353
thatd86f49d2015-03-15 00:56:57 +0100354 Layout& lay = layouts[currentLayout - 1];
Dees_Troy51a0e822012-09-05 15:24:24 -0400355
thatf6b20662015-06-25 21:51:37 +0200356 bool drawKeys = false;
thatd86f49d2015-03-15 00:56:57 +0100357 if (lay.keyboardImg && lay.keyboardImg->GetResource())
thatf6b20662015-06-25 21:51:37 +0200358 // keyboard is image based
thatf256b722015-05-23 20:44:12 +0200359 gr_blit(lay.keyboardImg->GetResource(), 0, 0, mRenderW, mRenderH, mRenderX, mRenderY);
360 else {
thatf6b20662015-06-25 21:51:37 +0200361 // keyboard is software drawn
362 // fill background
thatf256b722015-05-23 20:44:12 +0200363 gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, mBackgroundColor.alpha);
364 gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
thatf6b20662015-06-25 21:51:37 +0200365 drawKeys = true;
366 }
thatf256b722015-05-23 20:44:12 +0200367
thatf6b20662015-06-25 21:51:37 +0200368 // draw keys
369 int y1 = 0;
370 for (int row = 0; row < MAX_KEYBOARD_ROWS; ++row) {
371 int rowY = mRenderY + y1;
372 int rowH = lay.row_end_y[row] - y1;
373 y1 = lay.row_end_y[row];
374 int x1 = 0;
375 for (int col = 0; col < MAX_KEYBOARD_KEYS; ++col) {
376 Key& key = lay.keys[row][col];
377 int keyY = rowY;
378 int keyH = rowH;
379 int keyX = mRenderX + x1;
380 int keyW = key.end_x - x1;
381 x1 = key.end_x;
thatf256b722015-05-23 20:44:12 +0200382
thatf6b20662015-06-25 21:51:37 +0200383 // Draw key for software drawn keyboard
384 if (drawKeys)
385 DrawKey(key, keyX, keyY, keyW, keyH);
386
387 // Draw highlight for capslock
388 if (hasCapsHighlight && lay.is_caps && CapsLockOn && (int)key.key == KEYBOARD_LAYOUT && key.layout == lay.revert_layout) {
389 gr_color(mCapsHighlightColor.red, mCapsHighlightColor.green, mCapsHighlightColor.blue, mCapsHighlightColor.alpha);
thatf256b722015-05-23 20:44:12 +0200390 gr_fill(keyX, keyY, keyW, keyH);
thatf6b20662015-06-25 21:51:37 +0200391 }
thatf256b722015-05-23 20:44:12 +0200392
thatf6b20662015-06-25 21:51:37 +0200393 // Highlight current key
394 if (hasHighlight && &key == currentKey && highlightRenderCount != 0) {
395 gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, mHighlightColor.alpha);
396 gr_fill(keyX, keyY, keyW, keyH);
thatf256b722015-05-23 20:44:12 +0200397 }
398 }
399 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400400
thatf6b20662015-06-25 21:51:37 +0200401 if (!hasHighlight || highlightRenderCount == 0)
Dees_Troy30b962e2012-10-19 20:48:59 -0400402 mRendered = true;
thatf6b20662015-06-25 21:51:37 +0200403 else if (highlightRenderCount > 0)
404 highlightRenderCount--;
thatd86f49d2015-03-15 00:56:57 +0100405 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400406}
407
408int GUIKeyboard::Update(void)
409{
410 if (!isConditionTrue()) return (mRendered ? 2 : 0);
411 if (!mRendered) return 2;
412
413 return 0;
414}
415
416int GUIKeyboard::SetRenderPos(int x, int y, int w, int h)
417{
thatf256b722015-05-23 20:44:12 +0200418 RenderObject::SetRenderPos(x, y, w, h);
Dees_Troy51a0e822012-09-05 15:24:24 -0400419 SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
420 return 0;
421}
422
thate79878b2015-03-14 23:07:23 +0100423GUIKeyboard::Key* GUIKeyboard::HitTestKey(int x, int y)
Dees_Troy51a0e822012-09-05 15:24:24 -0400424{
thate79878b2015-03-14 23:07:23 +0100425 if (!IsInRegion(x, y))
426 return NULL;
427
428 int rely = y - mRenderY;
429 int relx = x - mRenderX;
430
thatd86f49d2015-03-15 00:56:57 +0100431 Layout& lay = layouts[currentLayout - 1];
432
thate79878b2015-03-14 23:07:23 +0100433 // Find the correct row
434 int row;
435 for (row = 0; row < MAX_KEYBOARD_ROWS; ++row) {
thatd86f49d2015-03-15 00:56:57 +0100436 if (lay.row_end_y[row] > rely)
thate79878b2015-03-14 23:07:23 +0100437 break;
438 }
439 if (row == MAX_KEYBOARD_ROWS)
440 return NULL;
441
442 // Find the correct key (column)
443 int col;
444 int x1 = 0;
445 for (col = 0; col < MAX_KEYBOARD_KEYS; ++col) {
thatd86f49d2015-03-15 00:56:57 +0100446 Key& key = lay.keys[row][col];
thate79878b2015-03-14 23:07:23 +0100447 if (x1 <= relx && relx < key.end_x && key.key != 0) {
448 // This is the key that was pressed!
thate79878b2015-03-14 23:07:23 +0100449 return &key;
450 }
451 x1 = key.end_x;
452 }
453 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400454}
455
456int GUIKeyboard::NotifyTouch(TOUCH_STATE state, int x, int y)
457{
thate79878b2015-03-14 23:07:23 +0100458 static int was_held = 0, startX = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400459
460 if (!isConditionTrue()) return -1;
461
462 switch (state)
463 {
464 case TOUCH_START:
thate79878b2015-03-14 23:07:23 +0100465 was_held = 0;
466 startX = x;
thatf6b20662015-06-25 21:51:37 +0200467 currentKey = HitTestKey(x, y);
468 if (currentKey)
thate79878b2015-03-14 23:07:23 +0100469 highlightRenderCount = -1;
470 else
Dees_Troy30b962e2012-10-19 20:48:59 -0400471 highlightRenderCount = 0;
thate79878b2015-03-14 23:07:23 +0100472 mRendered = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400473 break;
thate79878b2015-03-14 23:07:23 +0100474
Dees_Troy51a0e822012-09-05 15:24:24 -0400475 case TOUCH_DRAG:
476 break;
thate79878b2015-03-14 23:07:23 +0100477
Dees_Troy51a0e822012-09-05 15:24:24 -0400478 case TOUCH_RELEASE:
thatf256b722015-05-23 20:44:12 +0200479 if (x < startX - (mRenderW * 0.5)) {
Dees_Troy30b962e2012-10-19 20:48:59 -0400480 if (highlightRenderCount != 0) {
481 highlightRenderCount = 0;
482 mRendered = false;
483 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400484 PageManager::NotifyKeyboard(KEYBOARD_SWIPE_LEFT);
485 return 0;
thatf256b722015-05-23 20:44:12 +0200486 } else if (x > startX + (mRenderW * 0.5)) {
Dees_Troy30b962e2012-10-19 20:48:59 -0400487 if (highlightRenderCount != 0) {
488 highlightRenderCount = 0;
489 mRendered = false;
490 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400491 PageManager::NotifyKeyboard(KEYBOARD_SWIPE_RIGHT);
492 return 0;
493 }
thate79878b2015-03-14 23:07:23 +0100494 // fall through
Dees_Troy51a0e822012-09-05 15:24:24 -0400495 case TOUCH_HOLD:
496 case TOUCH_REPEAT:
thatf6b20662015-06-25 21:51:37 +0200497 if (!currentKey) {
Dees_Troy30b962e2012-10-19 20:48:59 -0400498 if (highlightRenderCount != 0) {
499 highlightRenderCount = 0;
500 mRendered = false;
501 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400502 return 0;
thate79878b2015-03-14 23:07:23 +0100503 }
504
505 if (highlightRenderCount != 0) {
Dees_Troy30b962e2012-10-19 20:48:59 -0400506 if (state == TOUCH_RELEASE)
507 highlightRenderCount = 2;
508 else
509 highlightRenderCount = -1;
510 mRendered = false;
511 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400512
thatf6b20662015-06-25 21:51:37 +0200513 if (HitTestKey(x, y) != currentKey) {
thate79878b2015-03-14 23:07:23 +0100514 // We dragged off of the starting key
thatf6b20662015-06-25 21:51:37 +0200515 currentKey = NULL;
thate79878b2015-03-14 23:07:23 +0100516 if (highlightRenderCount != 0) {
517 highlightRenderCount = 0;
518 mRendered = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400519 }
thate79878b2015-03-14 23:07:23 +0100520 return 0;
521 } else {
thatf6b20662015-06-25 21:51:37 +0200522 Key& key = *currentKey;
thatd86f49d2015-03-15 00:56:57 +0100523 Layout& lay = layouts[currentLayout - 1];
thate79878b2015-03-14 23:07:23 +0100524 if (state == TOUCH_RELEASE && was_held == 0) {
525 DataManager::Vibrate("tw_keyboard_vibrate");
thatd86f49d2015-03-15 00:56:57 +0100526 if ((int)key.key == KEYBOARD_LAYOUT) {
thate79878b2015-03-14 23:07:23 +0100527 // Switch layouts
thatd86f49d2015-03-15 00:56:57 +0100528 if (lay.is_caps && key.layout == lay.revert_layout && !CapsLockOn) {
529 CapsLockOn = true; // Set the caps lock
thate79878b2015-03-14 23:07:23 +0100530 } else {
thatd86f49d2015-03-15 00:56:57 +0100531 CapsLockOn = false; // Unset the caps lock and change layouts
thate79878b2015-03-14 23:07:23 +0100532 currentLayout = key.layout;
Dees_Troy51a0e822012-09-05 15:24:24 -0400533 }
thate79878b2015-03-14 23:07:23 +0100534 mRendered = false;
535 } else if ((int)key.key == KEYBOARD_ACTION) {
536 // Action
537 highlightRenderCount = 0;
538 // Send action notification
539 PageManager::NotifyKeyboard(key.key);
thatd86f49d2015-03-15 00:56:57 +0100540 } else if ((int)key.key < KEYBOARD_SPECIAL_KEYS && (int)key.key > 0) {
541 // Regular key
542 PageManager::NotifyKeyboard(key.key);
543 if (!CapsLockOn && lay.is_caps) {
544 // caps lock was not set, change layouts
545 currentLayout = lay.revert_layout;
546 mRendered = false;
547 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400548 }
thate79878b2015-03-14 23:07:23 +0100549 } else if (state == TOUCH_HOLD) {
550 was_held = 1;
551 if ((int)key.key == KEYBOARD_BACKSPACE) {
552 // Repeat backspace
553 PageManager::NotifyKeyboard(key.key);
554 } else if ((int)key.longpresskey < KEYBOARD_SPECIAL_KEYS && (int)key.longpresskey > 0) {
555 // Long Press Key
556 DataManager::Vibrate("tw_keyboard_vibrate");
557 PageManager::NotifyKeyboard(key.longpresskey);
558 }
559 } else if (state == TOUCH_REPEAT) {
560 was_held = 1;
561 if ((int)key.key == KEYBOARD_BACKSPACE) {
562 // Repeat backspace
563 PageManager::NotifyKeyboard(key.key);
564 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400565 }
566 }
567 break;
568 }
569
570 return 0;
571}