Skip to content

Commit 12230e6

Browse files
committed
UI: experimental keypad to replace android keypad
1 parent aa5f17a commit 12230e6

File tree

5 files changed

+121
-92
lines changed

5 files changed

+121
-92
lines changed

CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ function(buildSDL)
101101
)
102102

103103
# message("SDL version: ${_SDL_VERSION}")
104-
set(BUILD_DATE `date +"%a, %d %b %Y"`)
105104
set(_SDL_VERSION ${_SDL_VERSION})
106105
set(_SDL ON)
107106
set(_UnixOS ON)

src/ui/image_codec.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
//
88
// Copyright(C) 2002-2025 Chris Warren-Smith.
99

10+
#include "config.h"
11+
#include <cstdio>
12+
#include <malloc.h>
1013
#include "image_codec.h"
1114
#include "lib/lodepng/lodepng.h"
1215

@@ -79,7 +82,7 @@ bool ImageCodec::encode(uint8_t **data, size_t *size) const {
7982
}
8083

8184
void ImageCodec::resize(unsigned width, unsigned height) {
82-
uint8_t *pixels = new uint8_t[width * height * 4];
85+
auto *pixels = new uint8_t[width * height * 4];
8386

8487
for (int y = 0; y < height; y++) {
8588
float gy = ((float)y + 0.5f) * _height / height - 0.5f;

src/ui/keycode.h

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,21 @@
99
#pragma once
1010

1111
enum KeyCode : char {
12-
K_UP = -1,
13-
K_DOWN = -2,
14-
K_LEFT = -3,
15-
K_RIGHT = -4,
16-
K_HOME = -5,
17-
K_END = -6,
18-
K_PAGE_UP = -7,
19-
K_PAGE_DOWN = -8,
20-
K_INSERT = -9,
21-
K_DELETE = -10,
22-
K_CUT = -11,
23-
K_COPY = -12,
24-
K_PASTE = -13,
25-
K_SAVE = -14,
26-
K_HELP = -15,
27-
K_SEARCH = -16,
28-
K_RUN = -17,
29-
K_TOGGLE = -18,
30-
K_SHIFT = -19,
31-
K_FIND = -20,
12+
K_CUT = (char)-1,
13+
K_COPY = (char)-2,
14+
K_PASTE = (char)-3,
15+
K_SAVE = (char)-4,
16+
K_HELP = (char)-5,
17+
K_SEARCH = (char)-6,
18+
K_RUN = (char)-7,
19+
K_TOGGLE = (char)-8,
20+
K_SHIFT = (char)-9,
21+
K_FIND = (char)-10,
22+
K_EXT1 = (char)-11,
23+
K_EXT2 = (char)-12,
24+
K_EXT3 = (char)-13,
25+
K_EXT4 = (char)-14,
26+
K_EXT5 = (char)-15,
3227
K_NULL = 0,
3328
K_BACKSPACE = 8,
3429
K_TAB = 9,
@@ -93,3 +88,7 @@ inline bool isNumber(KeyCode key) {
9388
return key >= K_0 && key <= K_9;
9489
}
9590

91+
inline bool isExtended(KeyCode key) {
92+
return key >= K_EXT5 && key <= K_EXT1;
93+
}
94+

src/ui/keypad.cpp

Lines changed: 94 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -14,46 +14,42 @@
1414
#include "ui/keypad_icons.h"
1515
#include "keypad.h"
1616

17-
constexpr int maxRows = 5;
18-
constexpr int maxCols = 10;
19-
constexpr int defaultPadding = 16;
17+
constexpr int MAX_ROWS = 5;
18+
constexpr int MAX_COLS = 10;
19+
constexpr int NARROW_ROW = 2;
20+
constexpr int SPACE_COLS = 3;
21+
constexpr int DEFAULT_PADDING = 24;
2022
constexpr double PI = 3.14159;
2123

22-
KeypadTheme modernDarkTheme = {
23-
._bg = 0x101114, // Cool dark slate (true dark with a bluish tint)
24-
._key = 0x1c1e22, // Cool gray keys
25-
._keyHighlight = 0x2b2e34, // Slightly brighter for key press
26-
._text = 0xe4e6ea, // Icy white-gray text (bluish white)
27-
._outline = 0x2f3137, // Subtle cool gray outlines
28-
._funcKeyBg = 0x8e88aa, // Muted lavender-gray (soft cool purple)
29-
._funcKeyHighlight = 0xc6c2dc, // Light lavender highlight
30-
._funcText = 0xffffff, // Crisp white function key text
24+
KeypadTheme MODERN_DARK_THEME = {
25+
._bg = 0x0d0d0d, // Deep black background
26+
._key = 0x1a1a1a, // Dark gray keys
27+
._keyHighlight = 0x333333, // Slightly lighter for key press
28+
._text = 0xe0e0e0, // Soft white text
29+
._outline = 0x2a2a2a, // Subtle key outlines
30+
._funcKeyBg = 0x9f7aea, // Soft faint purple (Material Purple 300~400)
31+
._funcKeyHighlight = 0xd1c4e9, // Pale lavender for highlight effect
3132
};
3233

33-
constexpr RawKey letters[][maxCols] = {
34+
constexpr RawKey LETTERS[][MAX_COLS] = {
3435
{{K_CUT, K_CUT}, {K_COPY, K_COPY}, {K_PASTE, K_PASTE}, {K_SAVE, K_SAVE}, {K_RUN, K_RUN}, {K_HELP, K_HELP}},
3536
{{K_q, K_Q}, {K_w, K_W}, {K_e, K_E}, {K_r, K_R}, {K_t, K_T}, {K_y, K_Y}, {K_u, K_U}, {K_i, K_I}, {K_o, K_O}, {K_p, K_P}},
3637
{{K_a, K_A}, {K_s, K_S}, {K_d, K_D}, {K_f, K_F}, {K_g, K_G}, {K_h, K_H}, {K_j, K_J}, {K_k, K_K}, {K_l, K_L}},
3738
{{K_SHIFT, K_SHIFT}, {K_z, K_Z}, {K_x, K_X}, {K_c, K_C}, {K_v, K_V}, {K_b, K_B}, {K_n, K_N}, {K_m, K_M}, {K_BACKSPACE, K_BACKSPACE}},
38-
{{K_TOGGLE, K_TOGGLE}, {K_SPACE, K_SPACE}, {K_ENTER, K_ENTER}}
39+
{{K_TOGGLE, K_TOGGLE}, {K_LBRACKET, K_LPAREN}, {K_SPACE, K_SPACE}, {K_RBRACKET, K_RPAREN}, {K_ENTER, K_ENTER}}
3940
};
4041

41-
constexpr RawKey symbols[][maxCols] = {
42+
constexpr RawKey SYMBOLS[][MAX_COLS] = {
4243
{{K_CUT, K_CUT}, {K_COPY, K_COPY}, {K_PASTE, K_PASTE}, {K_SAVE, K_SAVE}, {K_RUN, K_RUN}, {K_HELP, K_HELP}},
4344
{{K_1, K_EXCLAIM}, {K_2, K_AT}, {K_3, K_HASH}, {K_4, K_DOLLAR}, {K_5, K_PERCENT}, {K_6, K_CARET}, {K_7, K_AMPERSAND}, {K_8, K_ASTERISK}, {K_9, K_LPAREN}, {K_0, K_RPAREN}},
44-
{{K_BACKTICK, K_TILDE}, {K_MINUS, K_UNDERSCORE}, {K_EQUALS, K_PLUS}, {K_LBRACKET, K_LBRACE}, {K_RBRACKET, K_RBRACE}, {K_BACKSLASH, K_PIPE}, {K_SEMICOLON, K_COLON}, {K_LPAREN, K_QUOTE}, {K_RPAREN, K_COMMA}},
45-
{{K_SHIFT, K_SHIFT}, {K_LESS, K_COMMA}, {K_GREATER, K_PERIOD}, {K_QUESTION, K_SLASH}, {K_SEMICOLON, K_COLON}, {K_APOSTROPHE, K_QUOTE}, {K_LBRACKET, K_LBRACE}, {K_RBRACKET, K_RBRACE}, {K_BACKSPACE, K_BACKSPACE}},
46-
{{K_TOGGLE, K_TOGGLE}, {K_SPACE, K_SPACE}, {K_ENTER, K_ENTER}}
45+
{{K_BACKTICK, K_TILDE}, {K_MINUS, K_UNDERSCORE}, {K_EQUALS, K_PLUS}, {K_LBRACKET, K_LBRACE}, {K_RBRACKET, K_RBRACE}, {K_BACKSLASH, K_PIPE}, {K_SEMICOLON, K_COLON}, {K_APOSTROPHE, K_QUOTE}, {K_HASH, K_EXT1}},
46+
{{K_SHIFT, K_SHIFT}, {K_LESS, K_COMMA}, {K_GREATER, K_PERIOD}, {K_QUESTION, K_SLASH}, {K_PLUS, K_EXT2}, {K_ASTERISK, K_EXT3}, {K_LPAREN, K_EXT4}, {K_RPAREN, K_EXT5}, {K_BACKSPACE, K_BACKSPACE}},
47+
{{K_TOGGLE, K_TOGGLE}, {K_LBRACKET, K_LPAREN}, {K_SPACE, K_SPACE}, {K_RBRACKET, K_RPAREN}, {K_ENTER, K_ENTER}}
4748
};
4849

49-
constexpr int rowLengths[][5] = {
50-
{6, 10, 9, 9, 3}, // letters
51-
{6, 10, 9, 9, 3}, // symbols
52-
};
53-
54-
constexpr int rowCharLengths[][5] = {
55-
{12, 10, 9, 12, 14},// letters
56-
{12, 10, 9, 12, 14},// letters
50+
constexpr int ROW_LENGTHS[][5] = {
51+
{6, 10, 9, 9, 7}, // letters
52+
{6, 10, 9, 9, 7}, // symbols
5753
};
5854

5955
//
@@ -104,20 +100,16 @@ KeypadDrawContext::KeypadDrawContext(int charWidth, int charHeight) :
104100
!_searchImage.decode(img_search, img_search_len) ||
105101
!_shiftImage.decode(img_keyboard_shift, img_keyboard_shift_len) ||
106102
!_toggleImage.decode(img_keyboard, img_keyboard_len)) {
107-
deviceLog(_cutImage.getLastError());
103+
deviceLog("%s", _cutImage.getLastError());
108104
}
109105
}
110106

111107
void KeypadDrawContext::toggleShift() {
112108
_shiftActive = !_shiftActive;
113109
}
114110

115-
bool KeypadDrawContext::useShift(bool specialKey) {
116-
bool useShift = _shiftActive ^ _capsLockActive;
117-
if (_shiftActive && !specialKey) {
118-
_shiftActive = false;
119-
}
120-
return useShift;
111+
bool KeypadDrawContext::useShift() const {
112+
return _shiftActive ^ _capsLockActive;
121113
}
122114

123115
const KeypadImage *KeypadDrawContext::getImage(const KeyCode keycode) const {
@@ -147,12 +139,12 @@ Key::Key(const RawKey &k) :
147139
_alt(k._shifted) {
148140
_pressed = false;
149141
_number = isNumber(k._normal);
150-
_printable = isPrintable(k._normal);
142+
_printable = isPrintable(k._normal) || isExtended(k._normal);
151143
}
152144

153145
int Key::color(const KeypadTheme *theme, bool shiftActive) const {
154146
int result;
155-
if (_pressed || ((_key == K_SHIFT) && shiftActive)) {
147+
if ((_key == K_SHIFT) && shiftActive) {
156148
result = !_printable ? theme->_funcKeyHighlight : theme->_keyHighlight;
157149
} else if (_number) {
158150
result = theme->_funcKeyHighlight;
@@ -162,6 +154,22 @@ int Key::color(const KeypadTheme *theme, bool shiftActive) const {
162154
return result;
163155
}
164156

157+
char Key::getKey(bool useShift) const {
158+
char result;
159+
KeyCode keyCode = useShift ? _alt : _key;
160+
switch (keyCode) {
161+
case K_EXT1: result = 164; break;
162+
case K_EXT2: result = 172; break;
163+
case K_EXT3: result = 182; break;
164+
case K_EXT4: result = 222; break;
165+
case K_EXT5: result = 223; break;
166+
default:
167+
result = keyCode;
168+
break;
169+
}
170+
return result;
171+
}
172+
165173
void Key::draw(const KeypadTheme *theme, const KeypadDrawContext *context) const {
166174
int rc = 5;
167175
int pad = 2;
@@ -177,10 +185,20 @@ void Key::draw(const KeypadTheme *theme, const KeypadDrawContext *context) const
177185
int ycB = by - rc; // y center for bottom arcs
178186

179187
// Set background color
180-
maSetColor(_printable ? theme->_key : theme->_funcKeyBg);
181-
maFillRect(_x, _y, _w, _h);
188+
if (_printable) {
189+
maSetColor(theme->_key);
190+
maFillRect(_x, _y, _w, _h);
191+
} else {
192+
maSetColor(theme->_funcKeyBg);
193+
maFillRect(_x + 1, _y + 1, _w - 2, _h - 2);
194+
}
182195

183196
if (_printable || _pressed) {
197+
if (_printable && _pressed) {
198+
maSetColor(theme->_outline);
199+
maFillRect(_x + 4, _y + 4, _w - 8, _h - 8);
200+
}
201+
184202
maSetColor(_printable ? theme->_keyHighlight : theme->_funcKeyHighlight);
185203

186204
// Draw edges (excluding the rounded corners)
@@ -196,7 +214,7 @@ void Key::draw(const KeypadTheme *theme, const KeypadDrawContext *context) const
196214
maArc(xcR, ycT, rc, PI * 3 / 2, 0, aspect); // Top-right corner
197215
maArc(xcR, ycB, rc, 0, PI / 2, aspect); // Bottom-right corner
198216
maArc(xcL, ycB, rc, PI / 2, PI, aspect); // Bottom-left corner
199-
}
217+
}
200218

201219
if (_printable) {
202220
bool useShift = context->_shiftActive ^ context->_capsLockActive;
@@ -205,6 +223,9 @@ void Key::draw(const KeypadTheme *theme, const KeypadDrawContext *context) const
205223
int yOffset = (_h - context->_charHeight) / 2;
206224
int textX = _x + xOffset;
207225
int textY = _y + yOffset;
226+
if (isExtended(useShift ? _alt : _key)) {
227+
key[0] = getKey(useShift);
228+
}
208229
maSetColor(color(theme, context->_shiftActive));
209230
maDrawText(textX, textY, key, 1);
210231
} else {
@@ -222,7 +243,7 @@ bool Key::inside(int x, int y) const {
222243
y <= _y + _h);
223244
}
224245

225-
void Key::onClick(bool useShift) {
246+
void Key::onClick(bool useShift) const {
226247
auto *event = new MAEvent();
227248
event->type = EVENT_TYPE_KEY_PRESSED;
228249
event->nativeKey = 0;
@@ -258,7 +279,7 @@ void Key::onClick(bool useShift) {
258279
event->key = SB_KEY_F(1);
259280
break;
260281
default:
261-
event->key = _key;
282+
event->key = getKey(useShift);
262283
break;
263284
}
264285
maPushEvent(event);
@@ -273,30 +294,30 @@ Keypad::Keypad(int charWidth, int charHeight)
273294
_width(0),
274295
_height(0),
275296
_context(charWidth, charHeight),
276-
_theme(&modernDarkTheme),
297+
_theme(&MODERN_DARK_THEME),
277298
_currentLayout(LayoutLetters) {
278299
generateKeys();
279300
}
280301

281302
int Keypad::outerHeight(int charHeight) {
282-
return maxRows * ((defaultPadding * 2) + charHeight);
303+
return MAX_ROWS * ((DEFAULT_PADDING * 2) + charHeight);
283304
}
284305

285306
void Keypad::generateKeys() {
286307
_keys.clear();
287308

288-
const RawKey (*activeLayout)[maxCols];
309+
const RawKey (*activeLayout)[MAX_COLS];
289310
switch (_currentLayout) {
290311
case LayoutLetters:
291-
activeLayout = letters;
312+
activeLayout = LETTERS;
292313
break;
293314
default:
294-
activeLayout = symbols;
315+
activeLayout = SYMBOLS;
295316
break;
296317
}
297318

298-
for (int row = 0; row < maxRows; ++row) {
299-
int cols = rowLengths[_currentLayout][row];
319+
for (int row = 0; row < MAX_ROWS; ++row) {
320+
int cols = ROW_LENGTHS[_currentLayout][row];
300321
for (int col = 0; col < cols; col++) {
301322
const RawKey &k = activeLayout[row][col];
302323
if (k._normal != K_NULL) {
@@ -316,27 +337,27 @@ void Keypad::layout(int x, int y, int w, int h) {
316337
const int charHeight = _context._charHeight;
317338

318339
// start with optimum padding, then reduce to fit width
319-
int padding = defaultPadding;
320-
int width = maxCols * (charWidth + (padding * 2));
340+
int padding = DEFAULT_PADDING;
341+
int width = MAX_COLS * (charWidth + (padding * 2));
321342

322343
while (width > w && padding > 0) {
323-
padding--;
324-
width = maxCols * (charWidth + (padding * 2));
344+
padding -= 2;
345+
width = MAX_COLS * (charWidth + (padding * 2));
325346
}
347+
padding *= 2;
326348

327-
int keyW = charWidth + (padding * 2);
328-
int keyH = charHeight + (padding * 2);
349+
int keyW = charWidth + (padding);
350+
int keyH = charHeight + (padding);
329351
int xStart = _posX + ((w - width) / 2);
330352
int yPos = _posY;
331353
int index = 0;
354+
int boardWidth = (MAX_COLS * charWidth) + (MAX_COLS * padding);
332355

333-
for (int row = 0; row < maxRows; ++row) {
334-
int cols = rowLengths[_currentLayout][row];
335-
int chars = rowCharLengths[_currentLayout][row];
356+
for (int row = 0; row < MAX_ROWS; ++row) {
357+
int cols = ROW_LENGTHS[_currentLayout][row];
336358
int xPos = xStart;
337-
if (cols < maxCols) {
338-
// center narrow row
339-
int rowWidth = (chars * charWidth) + (cols * padding * 2);
359+
if (row == NARROW_ROW) {
360+
int rowWidth = (cols * charWidth) + (cols * padding);
340361
if (rowWidth > width) {
341362
xPos -= (rowWidth - width) / 2;
342363
} else {
@@ -350,11 +371,18 @@ void Keypad::layout(int x, int y, int w, int h) {
350371
Key *key = _keys[index++];
351372
int length = key->_printable ? 1 : 2;
352373
int keyWidth = keyW;
353-
if (key->_key == K_SPACE) {
354-
length = 12;
355-
}
356-
if (length > 1) {
357-
keyWidth = (length * charWidth) + (padding * 2);
374+
if (row == 0) {
375+
keyWidth = (boardWidth / cols);
376+
if (col < 2 || col > 3) {
377+
keyWidth += 1;
378+
}
379+
} else if (!key->_printable) {
380+
int numKeys = 2;
381+
keyWidth = (boardWidth - ((cols - numKeys) * keyW)) / numKeys;
382+
} else if (key->_key == K_SPACE) {
383+
keyWidth = (SPACE_COLS * keyW);
384+
} else if (length > 1) {
385+
keyWidth = (length * charWidth) + (padding);
358386
}
359387
key->_x = xPos;
360388
key->_y = yPos;
@@ -380,7 +408,7 @@ void Keypad::clicked(int x, int y, bool pressed) {
380408
layout(_posX, _posY, _width, _height);
381409
break;
382410
} else {
383-
key->onClick(_context.useShift(!key->_printable));
411+
key->onClick(_context.useShift());
384412
}
385413
break;
386414
}
@@ -423,7 +451,7 @@ void KeypadInput::draw(int x, int y, int w, int h, int chw) {
423451
if (_keypad) {
424452
_keypad->draw();
425453
} else {
426-
maSetColor(modernDarkTheme._bg);
454+
maSetColor(MODERN_DARK_THEME._bg);
427455
maFillRect(x, y, _width, _height);
428456
}
429457
}

0 commit comments

Comments
 (0)