From a10df262b1742c31cad47085555e45b8f03ff4fc Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sun, 23 Jun 2024 10:45:46 +1000 Subject: [PATCH] Virtual keyboard: Support numpad layout too --- src/Input.c | 14 ++-- src/Input.h | 2 +- src/LScreens.c | 11 ++-- src/Platform_NDS.c | 1 - src/VirtualKeyboard.h | 147 ++++++++++++++++++++++++++---------------- src/Widgets.c | 8 +-- src/Window_3DS.c | 7 +- src/Window_NDS.c | 9 ++- 8 files changed, 121 insertions(+), 78 deletions(-) diff --git a/src/Input.c b/src/Input.c index 0f3f8719d..99e970eaa 100644 --- a/src/Input.c +++ b/src/Input.c @@ -310,13 +310,13 @@ void Input_Clear(void) { ClearTouches(); } -int Input_CalcDelta(int key, int horDelta, int verDelta) { - if (Input_IsLeftButton(key) || key == CCKEY_KP4) return -horDelta; - if (Input_IsRightButton(key) || key == CCKEY_KP6) return +horDelta; - if (Input_IsUpButton(key) || key == CCKEY_KP8) return -verDelta; - if (Input_IsDownButton(key) || key == CCKEY_KP2) return +verDelta; - - return 0; +void Input_CalcDelta(int key, int* horDelta, int* verDelta) { + *horDelta = 0; *verDelta = 0; + + if (Input_IsLeftButton(key) || key == CCKEY_KP4) *horDelta = -1; + if (Input_IsRightButton(key) || key == CCKEY_KP6) *horDelta = +1; + if (Input_IsUpButton(key) || key == CCKEY_KP8) *verDelta = -1; + if (Input_IsDownButton(key) || key == CCKEY_KP2) *verDelta = +1; } diff --git a/src/Input.h b/src/Input.h index f1ade210f..e939f9e62 100644 --- a/src/Input.h +++ b/src/Input.h @@ -114,7 +114,7 @@ void Input_Clear(void); #else #define Input_IsActionPressed() Input_IsCtrlPressed() #endif -int Input_CalcDelta(int btn, int horDelta, int verDelta); +void Input_CalcDelta(int btn, int* horDelta, int* verDelta); #ifdef CC_BUILD_TOUCH diff --git a/src/LScreens.c b/src/LScreens.c index 8f618780b..395be7658 100644 --- a/src/LScreens.c +++ b/src/LScreens.c @@ -372,12 +372,13 @@ static void ColoursScreen_AdjustSelected(struct LScreen* s, int delta) { } static void ColoursScreen_KeyDown(struct LScreen* s, int key, cc_bool was) { - int delta = Input_CalcDelta(key, 1, 10); - if (key == CCWHEEL_UP) delta = +1; - if (key == CCWHEEL_DOWN) delta = -1; + int deltaX, deltaY; + Input_CalcDelta(key, &deltaX, &deltaY); + if (key == CCWHEEL_UP) deltaX = +1; + if (key == CCWHEEL_DOWN) deltaX = -1; - if (delta) { - ColoursScreen_AdjustSelected(s, delta); + if (deltaX || deltaY) { + ColoursScreen_AdjustSelected(s, deltaY * 10 + deltaX); } else { LScreen_KeyDown(s, key, was); } diff --git a/src/Platform_NDS.c b/src/Platform_NDS.c index 7fbb189a2..97c735265 100644 --- a/src/Platform_NDS.c +++ b/src/Platform_NDS.c @@ -39,7 +39,6 @@ const cc_result ReturnCode_SocketInProgess = EINPROGRESS; const cc_result ReturnCode_SocketWouldBlock = EWOULDBLOCK; const cc_result ReturnCode_DirectoryExists = EEXIST; const char* Platform_AppNameSuffix = " NDS"; -extern cc_bool keyboardOpen; /*########################################################################################################################* diff --git a/src/VirtualKeyboard.h b/src/VirtualKeyboard.h index 08cdc6a28..9250fe14b 100644 --- a/src/VirtualKeyboard.h +++ b/src/VirtualKeyboard.h @@ -12,22 +12,13 @@ static cc_bool kb_inited, kb_shift, kb_needsHook; static struct FontDesc kb_font; -static int kb_selected; -static const char** kb_table; +static int kb_curX, kb_curY; static float kb_padXAcc, kb_padYAcc; static char kb_buffer[512]; static cc_string kb_str = String_FromArray(kb_buffer); static void (*KB_MarkDirty)(void); -#define KB_CELLS_PER_ROW 13 -#define KB_LAST_CELL (KB_CELLS_PER_ROW - 1) -#define KB_TOTAL_ROWS 5 -#define KB_LAST_ROW (KB_TOTAL_ROWS - 1) - -#define KB_TOTAL_CHARS (KB_CELLS_PER_ROW * 4) + 4 -#define KB_TOTAL_SIZE KB_CELLS_PER_ROW * KB_TOTAL_ROWS - -#define KB_TILE_SIZE 32 +#define KB_TILE_SIZE 32 #define KB_B_CAPS 0x10 #define KB_B_SHIFT 0x20 @@ -36,34 +27,74 @@ static void (*KB_MarkDirty)(void); #define KB_B_BACK 0x50 #define KB_B_ENTER 0x60 -#define KB_GetBehaviour(i) (kb_table_behaviour[i] & 0xF0) -#define KB_GetCellWidth(i) (kb_table_behaviour[i] & 0x0F) +#define KB_GetBehaviour(i) (kb->behaviour[i] & 0xF0) +#define KB_GetCellWidth(i) (kb->behaviour[i] & 0x0F) +#define KB_IsInvisible(i) (kb->behaviour[i] == 0) -static const char* kb_table_lower[] = +struct KBLayout { + int numRows, cellsPerRow, rowWidth; + const char** lower; + const char** upper; + const char** table; + const cc_uint8* behaviour; +}; +static struct KBLayout* kb; + + +static const char* kb_normal_lower[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", "Backspace", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "(", ")", "& ", "a", "s", "d", "f", "g", "h", "j", "k", "l", "?", ";", "'", "Enter", "z", "x", "c", "v", "b", "n", "m", ".", ",","\\", "!", "@", "/ ", - "Caps", "Shift", "Space", "Close" + "Caps",0,0,0, "Shift",0,0,0, "Space",0,0,0, "Close" }; -static const char* kb_table_upper[] = +static const char* kb_normal_upper[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "_", "+", "Backspace", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "[", "]", "& ", "A", "S", "D", "F", "G", "H", "J", "K", "L", "?", ":", "\"", "Enter", "Z", "X", "C", "V", "B", "N", "M", "<", ">", "*", "%", "#", "/ ", - "Caps", "Shift", "Space", "Close" + "Caps",0,0,0, "Shift",0,0,0, "Space",0,0,0, "Close" }; -static const cc_uint8 kb_table_behaviour[] = +static const cc_uint8 kb_normal_behaviour[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, KB_B_BACK | 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, KB_B_ENTER | 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, - KB_B_CAPS | 4, KB_B_SHIFT | 4, KB_B_SPACE | 4, KB_B_CLOSE | 4 + KB_B_CAPS | 4,0,0,0, KB_B_SHIFT | 4,0,0,0, KB_B_SPACE | 4,0,0,0, KB_B_CLOSE | 4 }; +static struct KBLayout normal_layout = { + 5, 13, 16, // 12 normal cells, 1 four wide cell + kb_normal_lower, kb_normal_upper, kb_normal_lower, + kb_normal_behaviour +}; + + +static const char* kb_numpad[] = +{ + "1", "2", "3", "Backspace", + "4", "5", "6", "Enter", + "7", "8", "9", "Space", + "-", "0", ".", "Close", +}; +static const cc_uint8 kb_numpad_behaviour[] = +{ + 1, 1, 1, KB_B_BACK | 4, + 1, 1, 1, KB_B_ENTER | 4, + 1, 1, 1, KB_B_SPACE | 4, + 1, 1, 1, KB_B_CLOSE | 4 +}; + +static struct KBLayout numpad_layout = { + 4, 4, 7, // 3 normal cells, 1 four wide cell + kb_numpad, kb_numpad, kb_numpad, + kb_numpad_behaviour +}; + + extern void LWidget_DrawBorder(struct Context2D* ctx, BitmapCol color, int borderX, int borderY, int x, int y, int width, int height); @@ -74,22 +105,23 @@ static void VirtualKeyboard_Init(void) { } static int VirtualKeyboard_Width(void) { - return (KB_CELLS_PER_ROW + 3) * KB_TILE_SIZE; + return kb->rowWidth * KB_TILE_SIZE; } static int VirtualKeyboard_Height(void) { - return KB_TOTAL_ROWS * KB_TILE_SIZE; + return kb->numRows * KB_TILE_SIZE; } + static int VirtualKeyboard_GetSelected(void) { - // Last row needs special handling since it uses 4 cells per item - int selected = kb_selected; - if (selected < 0) return -1; + if (kb_curX < 0) return -1; + int maxCells = kb->cellsPerRow * kb->numRows; + + int idx = kb_curX + kb->cellsPerRow * kb_curY; + Math_Clamp(idx, 0, maxCells - 1); - int row = selected / KB_CELLS_PER_ROW; - int cell = selected % KB_CELLS_PER_ROW; - if (row != KB_LAST_ROW) return selected; - cell /= 4; - return row * KB_CELLS_PER_ROW + cell; + // Skip over invisible cells + while (KB_IsInvisible(idx)) idx--; + return idx; } static void VirtualKeyboard_Close(void); @@ -104,20 +136,19 @@ static void VirtualKeyboard_Draw(struct Context2D* ctx) { struct DrawTextArgs args; cc_string str; int row, cell; - int i, x, y, w, h, dx, dy; + int i = 0, x, y, w, h, dx, dy; int selected = VirtualKeyboard_GetSelected(); Drawer2D.Colors['f'] = Drawer2D.Colors['0']; if (kb_needsHook) VirtualKeyboard_Hook(); - for (row = 0, y = 0; row < KB_TOTAL_ROWS; row++) + for (row = 0, y = 0; row < kb->numRows; row++) { - for (cell = 0, x = 0; cell < KB_CELLS_PER_ROW; cell++) + for (cell = 0, x = 0; cell < kb->cellsPerRow; cell++, i++) { - i = row * KB_CELLS_PER_ROW + cell; - if (i >= KB_TOTAL_CHARS) break; + if (KB_IsInvisible(i)) continue; - str = String_FromReadonly(kb_table[i]); + str = String_FromReadonly(kb->table[i]); DrawTextArgs_Make(&args, &str, &kb_font, false); w = KB_TILE_SIZE * KB_GetCellWidth(i); h = KB_TILE_SIZE; @@ -136,6 +167,7 @@ static void VirtualKeyboard_Draw(struct Context2D* ctx) { Drawer2D.Colors['f'] = Drawer2D.Colors['F']; } + static void VirtualKeyboard_CalcPosition(int* x, int* y, int width, int height) { /* Draw virtual keyboard at centre of window bottom */ *y = height - 1 - VirtualKeyboard_Height(); @@ -148,19 +180,23 @@ static void VirtualKeyboard_CalcPosition(int* x, int* y, int width, int height) /*########################################################################################################################* *-----------------------------------------------------Input handling------------------------------------------------------* *#########################################################################################################################*/ -static void VirtualKeyboard_Scroll(int delta) { - if (kb_selected < 0) kb_selected = 0; +static void VirtualKeyboard_Scroll(int xDelta, int yDelta) { + int perRow = kb->cellsPerRow, numRows = kb->numRows; + if (kb_curX < 0) kb_curX = 0; - kb_selected += delta; - if (kb_selected < 0) kb_selected += KB_TOTAL_SIZE; - if (kb_selected >= KB_TOTAL_SIZE) kb_selected -= KB_TOTAL_SIZE; + kb_curX += xDelta; + if (kb_curX < 0) kb_curX += perRow; + if (kb_curX >= perRow) kb_curX -= perRow; + + kb_curY += yDelta; + if (kb_curY < 0) kb_curY += numRows; + if (kb_curY >= numRows) kb_curY -= numRows; - Math_Clamp(kb_selected, 0, KB_TOTAL_SIZE - 1); KB_MarkDirty(); } static void VirtualKeyboard_ToggleTable(void) { - kb_table = kb_table == kb_table_lower ? kb_table_upper : kb_table_lower; + kb->table = kb->table == kb->lower ? kb->upper : kb->lower; KB_MarkDirty(); } @@ -180,11 +216,8 @@ static void VirtualKeyboard_Backspace(void) { static void VirtualKeyboard_ClickSelected(void) { int selected = VirtualKeyboard_GetSelected(); if (selected < 0) return; - int behaviour = KB_GetBehaviour(selected); - int B = kb_table_behaviour[selected]; - Platform_Log2("%i, %i", &B, &behaviour); - switch (behaviour) { + switch (KB_GetBehaviour(selected)) { case KB_B_BACK: VirtualKeyboard_Backspace(); break; @@ -209,15 +242,17 @@ static void VirtualKeyboard_ClickSelected(void) { break; default: - VirtualKeyboard_AppendChar(kb_table[selected][0]); + VirtualKeyboard_AppendChar(kb->table[selected][0]); break; } } static void VirtualKeyboard_ProcessDown(void* obj, int key, cc_bool was) { - int delta = Input_CalcDelta(key, 1, KB_CELLS_PER_ROW); - if (delta) { - VirtualKeyboard_Scroll(delta); + int deltaX, deltaY; + Input_CalcDelta(key, &deltaX, &deltaY); + + if (deltaX || deltaY) { + VirtualKeyboard_Scroll(deltaX, deltaY); } else if (key == CCPAD_START || key == CCPAD_A) { VirtualKeyboard_ClickSelected(); } else if (key == CCPAD_SELECT || key == CCPAD_B) { @@ -237,10 +272,10 @@ static void VirtualKeyboard_PadAxis(void* obj, int port, int axis, float x, floa int xSteps, ySteps; xSteps = Utils_AccumulateWheelDelta(&kb_padXAcc, x / 100.0f); - if (xSteps) VirtualKeyboard_Scroll(xSteps > 0 ? 1 : -1); + if (xSteps) VirtualKeyboard_Scroll(xSteps > 0 ? 1 : -1, 0); ySteps = Utils_AccumulateWheelDelta(&kb_padYAcc, y / 100.0f); - if (ySteps) VirtualKeyboard_Scroll(ySteps > 0 ? KB_CELLS_PER_ROW : -KB_CELLS_PER_ROW); + if (ySteps) VirtualKeyboard_Scroll(0, ySteps > 0 ? 1 : -1); } @@ -346,12 +381,16 @@ static void VirtualKeyboard_Open(struct OpenKeyboardArgs* args, cc_bool launcher DisplayInfo.ShowingSoftKeyboard = true; kb_needsHook = true; - kb_table = kb_table_lower; - kb_selected = -1; + kb_curX = -1; + kb_curY = 0; kb_padXAcc = 0; kb_padYAcc = 0; kb_shift = false; + int mode = args->type & 0xFF; + int num = mode == KEYBOARD_TYPE_INTEGER || mode == KEYBOARD_TYPE_NUMBER; + kb = num ? &numpad_layout : &normal_layout; + kb_str.length = 0; String_AppendString(&kb_str, args->text); diff --git a/src/Widgets.c b/src/Widgets.c index 53b2bfd53..bb20a148b 100644 --- a/src/Widgets.c +++ b/src/Widgets.c @@ -964,12 +964,12 @@ static int TableWidget_PointerMove(void* widget, int id, int x, int y) { static int TableWidget_KeyDown(void* widget, int key) { struct TableWidget* w = (struct TableWidget*)widget; - int delta; + int deltaX, deltaY; if (w->selectedIndex == -1) return false; - delta = Input_CalcDelta(key, 1, w->blocksPerRow); - if (delta) { - TableWidget_ScrollRelative(w, delta); + Input_CalcDelta(key, &deltaX, &deltaY); + if (deltaX || deltaY) { + TableWidget_ScrollRelative(w, deltaX + deltaY * w->blocksPerRow); return true; } return false; diff --git a/src/Window_3DS.c b/src/Window_3DS.c index 96001f9af..fc6cc35e5 100644 --- a/src/Window_3DS.c +++ b/src/Window_3DS.c @@ -260,6 +260,7 @@ void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { } else if (mode == KEYBOARD_TYPE_NUMBER) { swkbdSetNumpadKeys(&swkbd, '-', '.'); } + DisplayInfo.ShowingSoftKeyboard = true; if (mode == KEYBOARD_TYPE_PASSWORD) swkbdSetPasswordMode(&swkbd, SWKBD_PASSWORD_HIDE_DELAY); @@ -274,7 +275,11 @@ void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { void OnscreenKeyboard_SetText(const cc_string* text) { } void OnscreenKeyboard_Draw2D(Rect2D* r, struct Bitmap* bmp) { } void OnscreenKeyboard_Draw3D(void) { } -void OnscreenKeyboard_Close(void) { /* TODO implement */ } + +void OnscreenKeyboard_Close(void) { + DisplayInfo.ShowingSoftKeyboard = false; + /* TODO implement */ +} /*########################################################################################################################* diff --git a/src/Window_NDS.c b/src/Window_NDS.c index d3c5167ba..e40fd0942 100644 --- a/src/Window_NDS.c +++ b/src/Window_NDS.c @@ -126,7 +126,6 @@ static void consoleInit(void) { *------------------------------------------------------General data-------------------------------------------------------* *#########################################################################################################################*/ static cc_bool launcherMode; -cc_bool keyboardOpen; static int bg_id; static u16* bg_ptr; @@ -211,7 +210,7 @@ static void ProcessTouchInput(int mods) { void Window_ProcessEvents(float delta) { scanKeys(); - if (keyboardOpen) { + if (DisplayInfo.ShowingSoftKeyboard) { keyboardUpdate(); } else { ProcessTouchInput(keysDown() | keysHeld()); @@ -317,7 +316,7 @@ void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { kbd->OnKeyPressed = OnKeyPressed; String_InitArray(kbText, kbBuffer); String_AppendString(&kbText, args->text); - keyboardOpen = true; + DisplayInfo.ShowingSoftKeyboard = true; } void OnscreenKeyboard_SetText(const cc_string* text) { } @@ -327,8 +326,8 @@ void OnscreenKeyboard_Draw3D(void) { } void OnscreenKeyboard_Close(void) { keyboardHide(); - if (!keyboardOpen) return; - keyboardOpen = false; + if (!DisplayInfo.ShowingSoftKeyboard) return; + DisplayInfo.ShowingSoftKeyboard = false; videoBgEnableSub(0); // show console }