diff options
author | WlodekM <[email protected]> | 2024-06-16 10:35:45 +0300 |
---|---|---|
committer | WlodekM <[email protected]> | 2024-06-16 10:35:45 +0300 |
commit | abef6da56913f1c55528103e60a50451a39628b1 (patch) | |
tree | b3c8092471ecbb73e568cd0d336efa0e7871ee8d /src/Window_WiiU.cpp |
initial commit
Diffstat (limited to 'src/Window_WiiU.cpp')
-rw-r--r-- | src/Window_WiiU.cpp | 610 |
1 files changed, 610 insertions, 0 deletions
diff --git a/src/Window_WiiU.cpp b/src/Window_WiiU.cpp new file mode 100644 index 0000000..31785b3 --- /dev/null +++ b/src/Window_WiiU.cpp @@ -0,0 +1,610 @@ +#include "Core.h" +#if defined CC_BUILD_WIIU +extern "C" { +#include "Window.h" +#include "Platform.h" +#include "Input.h" +#include "Event.h" +#include "String.h" +#include "Funcs.h" +#include "Bitmap.h" +#include "Errors.h" +#include "ExtMath.h" +#include "Graphics.h" +#include "Launcher.h" +#include <coreinit/memheap.h> +#include <coreinit/cache.h> +#include <coreinit/memfrmheap.h> +#include <coreinit/memdefaultheap.h> +#include <coreinit/memory.h> +#include <coreinit/screen.h> +#include <proc_ui/procui.h> +#include <gx2/display.h> +#include <vpad/input.h> +#include <whb/proc.h> +#include <padscore/kpad.h> +#include <whb/gfx.h> +#include <gx2/mem.h> +#include <coreinit/filesystem.h> +#include <coreinit/memdefaultheap.h> +} +#include <nn/swkbd.h> + +static cc_bool launcherMode; +static cc_bool keyboardOpen; +struct _DisplayData DisplayInfo; +struct _WindowData WindowInfo; +struct _WindowData Window_Alt; +cc_bool launcherTop; + + + +static void OnscreenKeyboard_Update(void); +static void OnscreenKeyboard_DrawTV(void); +static void OnscreenKeyboard_DrawDRC(void); + +static void LoadTVDimensions(void) { + switch(GX2GetSystemTVScanMode()) + { + case GX2_TV_SCAN_MODE_480I: + case GX2_TV_SCAN_MODE_480P: + DisplayInfo.Width = 854; + DisplayInfo.Height = 480; + break; + case GX2_TV_SCAN_MODE_1080I: + case GX2_TV_SCAN_MODE_1080P: + DisplayInfo.Width = 1920; + DisplayInfo.Height = 1080; + break; + case GX2_TV_SCAN_MODE_720P: + default: + DisplayInfo.Width = 1280; + DisplayInfo.Height = 720; + break; + } +} + +static uint32_t OnAcquired(void* context) { + Window_Main.Inactive = false; + Event_RaiseVoid(&WindowEvents.InactiveChanged); + return 0; +} + +static uint32_t OnReleased(void* context) { + Window_Main.Inactive = true; + Event_RaiseVoid(&WindowEvents.InactiveChanged); + return 0; +} + +void Window_PreInit(void) { + KPADInit(); + VPADInit(); + + ProcUIRegisterCallback(PROCUI_CALLBACK_ACQUIRE, OnAcquired, NULL, 100); + ProcUIRegisterCallback(PROCUI_CALLBACK_RELEASE, OnReleased, NULL, 100); +} + +void Window_Init(void) { + LoadTVDimensions(); + DisplayInfo.ScaleX = 1; + DisplayInfo.ScaleY = 1; + + Window_Main.Width = DisplayInfo.Width; + Window_Main.Height = DisplayInfo.Height; + Window_Main.Focused = true; + Window_Main.Exists = true; + + Input.Sources = INPUT_SOURCE_GAMEPAD; + DisplayInfo.ContentOffsetX = 10; + DisplayInfo.ContentOffsetY = 10; + + Window_Main.SoftKeyboard = SOFT_KEYBOARD_RESIZE; + Input_SetTouchMode(true); + + Window_Alt.Width = 854; + Window_Alt.Height = 480; + WHBGfxInit(); +} + +void Window_Free(void) { } + +// OSScreen is always this buffer size, regardless of the current TV resolution +#define OSSCREEN_TV_WIDTH 1280 +#define OSSCREEN_TV_HEIGHT 720 +#define OSSCREEN_DRC_WIDTH 854 +#define OSSCREEN_DRC_HEIGHT 480 +static void LauncherInactiveChanged(void* obj); +static void Init2DResources(void); + +void Window_Create2D(int width, int height) { + Window_Main.Width = OSSCREEN_DRC_WIDTH; + Window_Main.Height = OSSCREEN_DRC_HEIGHT; + + launcherMode = true; + Event_Register_(&WindowEvents.InactiveChanged, NULL, LauncherInactiveChanged); + Init2DResources(); +} + +void Window_Create3D(int width, int height) { + Window_Main.Width = DisplayInfo.Width; + Window_Main.Height = DisplayInfo.Height; + + launcherMode = false; + Event_Unregister_(&WindowEvents.InactiveChanged, NULL, LauncherInactiveChanged); +} + +void Window_RequestClose(void) { + Event_RaiseVoid(&WindowEvents.Closing); +} + + +/*########################################################################################################################* +*----------------------------------------------------Input processing-----------------------------------------------------* +*#########################################################################################################################*/ +extern Rect2D dirty_rect; +void Window_ProcessEvents(float delta) { + if (!dirty_rect.width) dirty_rect.width = 1; + + if (!WHBProcIsRunning()) { + Window_Main.Exists = false; + Window_RequestClose(); + } +} + +void Window_UpdateRawMouse(void) { } + +void Cursor_SetPosition(int x, int y) { } +void Window_EnableRawMouse(void) { Input.RawMode = true; } +void Window_DisableRawMouse(void) { Input.RawMode = false; } + + +/*########################################################################################################################* +*-------------------------------------------------------Gamepads----------------------------------------------------------* +*#########################################################################################################################*/ +static VPADStatus vpadStatus; +static bool kpad_valid[4]; +static KPADStatus kpads[4]; + +static void ProcessKPadButtons(int port, int mods) { + Gamepad_SetButton(port, CCPAD_L, mods & WPAD_BUTTON_1); + Gamepad_SetButton(port, CCPAD_R, mods & WPAD_BUTTON_2); + + Gamepad_SetButton(port, CCPAD_A, mods & WPAD_BUTTON_A); + Gamepad_SetButton(port, CCPAD_B, mods & WPAD_BUTTON_B); + Gamepad_SetButton(port, CCPAD_X, mods & WPAD_BUTTON_PLUS); + + Gamepad_SetButton(port, CCPAD_START, mods & WPAD_BUTTON_HOME); + Gamepad_SetButton(port, CCPAD_SELECT, mods & WPAD_BUTTON_MINUS); + + Gamepad_SetButton(port, CCPAD_LEFT, mods & WPAD_BUTTON_LEFT); + Gamepad_SetButton(port, CCPAD_RIGHT, mods & WPAD_BUTTON_RIGHT); + Gamepad_SetButton(port, CCPAD_UP, mods & WPAD_BUTTON_UP); + Gamepad_SetButton(port, CCPAD_DOWN, mods & WPAD_BUTTON_DOWN); +} + +static void ProcessNunchuckButtons(int port, int mods) { + Gamepad_SetButton(port, CCPAD_L, mods & WPAD_NUNCHUK_BUTTON_Z); + Gamepad_SetButton(port, CCPAD_R, mods & WPAD_NUNCHUK_BUTTON_C); +} + +static void ProcessClassicButtons(int port, int mods) { + Gamepad_SetButton(port, CCPAD_L, mods & WPAD_CLASSIC_BUTTON_L); + Gamepad_SetButton(port, CCPAD_R, mods & WPAD_CLASSIC_BUTTON_R); + Gamepad_SetButton(port, CCPAD_ZL, mods & WPAD_CLASSIC_BUTTON_ZL); + Gamepad_SetButton(port, CCPAD_ZR, mods & WPAD_CLASSIC_BUTTON_ZR); + + Gamepad_SetButton(port, CCPAD_A, mods & WPAD_CLASSIC_BUTTON_A); + Gamepad_SetButton(port, CCPAD_B, mods & WPAD_CLASSIC_BUTTON_B); + Gamepad_SetButton(port, CCPAD_X, mods & WPAD_CLASSIC_BUTTON_X); + Gamepad_SetButton(port, CCPAD_Y, mods & WPAD_CLASSIC_BUTTON_Y); + + Gamepad_SetButton(port, CCPAD_START, mods & WPAD_CLASSIC_BUTTON_HOME); + Gamepad_SetButton(port, CCPAD_SELECT, mods & WPAD_CLASSIC_BUTTON_MINUS); + Gamepad_SetButton(port, CCPAD_Z, mods & WPAD_CLASSIC_BUTTON_PLUS); + + Gamepad_SetButton(port, CCPAD_LEFT, mods & WPAD_CLASSIC_BUTTON_LEFT); + Gamepad_SetButton(port, CCPAD_RIGHT, mods & WPAD_CLASSIC_BUTTON_RIGHT); + Gamepad_SetButton(port, CCPAD_UP, mods & WPAD_CLASSIC_BUTTON_UP); + Gamepad_SetButton(port, CCPAD_DOWN, mods & WPAD_CLASSIC_BUTTON_DOWN); +} + +static void ProcessProButtons(int port, int mods) { + Gamepad_SetButton(port, CCPAD_L, mods & WPAD_PRO_TRIGGER_L); + Gamepad_SetButton(port, CCPAD_R, mods & WPAD_PRO_TRIGGER_R); + Gamepad_SetButton(port, CCPAD_ZL, mods & WPAD_PRO_TRIGGER_ZL); + Gamepad_SetButton(port, CCPAD_ZR, mods & WPAD_PRO_TRIGGER_ZR); + + Gamepad_SetButton(port, CCPAD_A, mods & WPAD_PRO_BUTTON_A); + Gamepad_SetButton(port, CCPAD_B, mods & WPAD_PRO_BUTTON_B); + Gamepad_SetButton(port, CCPAD_X, mods & WPAD_PRO_BUTTON_X); + Gamepad_SetButton(port, CCPAD_Y, mods & WPAD_PRO_BUTTON_Y); + + Gamepad_SetButton(port, CCPAD_START, mods & WPAD_PRO_BUTTON_HOME); + Gamepad_SetButton(port, CCPAD_SELECT, mods & WPAD_PRO_BUTTON_MINUS); + Gamepad_SetButton(port, CCPAD_Z, mods & WPAD_PRO_BUTTON_PLUS); + Gamepad_SetButton(port, CCPAD_LSTICK, mods & WPAD_PRO_BUTTON_STICK_L); + Gamepad_SetButton(port, CCPAD_RSTICK, mods & WPAD_PRO_BUTTON_STICK_R); + + Gamepad_SetButton(port, CCPAD_LEFT, mods & WPAD_PRO_BUTTON_LEFT); + Gamepad_SetButton(port, CCPAD_RIGHT, mods & WPAD_PRO_BUTTON_RIGHT); + Gamepad_SetButton(port, CCPAD_UP, mods & WPAD_PRO_BUTTON_UP); + Gamepad_SetButton(port, CCPAD_DOWN, mods & WPAD_PRO_BUTTON_DOWN); +} + +static void ProcessKPAD(float delta, int i) { + kpad_valid[i] = false; + int res = KPADRead((WPADChan)(WPAD_CHAN_0 + i), &kpads[i], 1); + + if (res != KPAD_ERROR_OK) return; + kpad_valid[i] = true; + + switch (kpads[i].extensionType) + { + case WPAD_EXT_CLASSIC: + ProcessClassicButtons(i, kpads[i].classic.hold | kpads[i].classic.trigger); + break; + case WPAD_EXT_PRO_CONTROLLER: + ProcessProButtons( i, kpads[i].pro.hold | kpads[i].pro.trigger); + break; + case WPAD_EXT_NUNCHUK: + ProcessKPadButtons(i, kpads[i].hold | kpads[i].trigger); + ProcessNunchuckButtons(i, kpads[i].nunchuck.hold | kpads[i].nunchuck.trigger); + break; + default: + ProcessKPadButtons(i, kpads[i].hold | kpads[i].trigger); + break; + } +} + + +#define AXIS_SCALE 4.0f +static void ProcessVpadStick(int port, int axis, float x, float y, float delta) { + // May not be exactly 0 on actual hardware + if (Math_AbsF(x) <= 0.1f) x = 0; + if (Math_AbsF(y) <= 0.1f) y = 0; + + Gamepad_SetAxis(port, axis, x * AXIS_SCALE, -y * AXIS_SCALE, delta); +} + +static void ProcessVpadButtons(int port, int mods) { + Gamepad_SetButton(port, CCPAD_L, mods & VPAD_BUTTON_L); + Gamepad_SetButton(port, CCPAD_R, mods & VPAD_BUTTON_R); + Gamepad_SetButton(port, CCPAD_ZL, mods & VPAD_BUTTON_ZL); + Gamepad_SetButton(port, CCPAD_ZR, mods & VPAD_BUTTON_ZR); + + Gamepad_SetButton(port, CCPAD_A, mods & VPAD_BUTTON_A); + Gamepad_SetButton(port, CCPAD_B, mods & VPAD_BUTTON_B); + Gamepad_SetButton(port, CCPAD_X, mods & VPAD_BUTTON_X); + Gamepad_SetButton(port, CCPAD_Y, mods & VPAD_BUTTON_Y); + + Gamepad_SetButton(port, CCPAD_START, mods & VPAD_BUTTON_PLUS); + Gamepad_SetButton(port, CCPAD_SELECT, mods & VPAD_BUTTON_MINUS); + + Gamepad_SetButton(port, CCPAD_LEFT, mods & VPAD_BUTTON_LEFT); + Gamepad_SetButton(port, CCPAD_RIGHT, mods & VPAD_BUTTON_RIGHT); + Gamepad_SetButton(port, CCPAD_UP, mods & VPAD_BUTTON_UP); + Gamepad_SetButton(port, CCPAD_DOWN, mods & VPAD_BUTTON_DOWN); + +} + +static void ProcessVpadTouch(VPADTouchData* data) { + static int was_touched; + + // TODO rescale to main screen size + if (data->touched) { + int x = data->x; + int y = data->y; + Platform_Log2("TOUCH: %i, %i", &x, &y); + + x = x * Window_Main.Width / 1280; + y = y * Window_Main.Height / 720; + + Input_AddTouch(0, x, y); + } else if (was_touched) { + Input_RemoveTouch(0, Pointers[0].x, Pointers[0].y); + } + was_touched = data->touched; +} + +static void ProcessVPAD(float delta) { + VPADReadError error = VPAD_READ_SUCCESS; + VPADRead(VPAD_CHAN_0, &vpadStatus, 1, &error); + if (error != VPAD_READ_SUCCESS) return; + + VPADGetTPCalibratedPoint(VPAD_CHAN_0, &vpadStatus.tpNormal, &vpadStatus.tpNormal); + ProcessVpadButtons(0, vpadStatus.hold); + ProcessVpadTouch(&vpadStatus.tpNormal); + + ProcessVpadStick(0, PAD_AXIS_LEFT, vpadStatus.leftStick.x, vpadStatus.leftStick.y, delta); + ProcessVpadStick(0, PAD_AXIS_RIGHT, vpadStatus.rightStick.x, vpadStatus.rightStick.y, delta); +} + + +void Window_ProcessGamepads(float delta) { + ProcessVPAD(delta); + for (int i = 0; i < 4; i++) + ProcessKPAD(delta, i); + + if (keyboardOpen) OnscreenKeyboard_Update(); +} + + +/*########################################################################################################################* +*------------------------------------------------------Framebuffer--------------------------------------------------------* +*#########################################################################################################################*/ +static GfxResourceID framebuffer_vb; + +static void LauncherInactiveChanged(void* obj) { + // TODO +} + +static void Init2DResources(void) { + Gfx_Create(); + if (framebuffer_vb) return; + + struct VertexTextured* data = (struct VertexTextured*)Gfx_RecreateAndLockVb(&framebuffer_vb, + VERTEX_FORMAT_TEXTURED, 4); + data[0].x = -1.0f; data[0].y = -1.0f; data[0].z = 0.0f; data[0].Col = PACKEDCOL_WHITE; data[0].U = 0.0f; data[0].V = 1.0f; + data[1].x = 1.0f; data[1].y = -1.0f; data[1].z = 0.0f; data[1].Col = PACKEDCOL_WHITE; data[1].U = 1.0f; data[1].V = 1.0f; + data[2].x = 1.0f; data[2].y = 1.0f; data[2].z = 0.0f; data[2].Col = PACKEDCOL_WHITE; data[2].U = 1.0f; data[2].V = 0.0f; + data[3].x = -1.0f; data[3].y = 1.0f; data[3].z = 0.0f; data[3].Col = PACKEDCOL_WHITE; data[3].U = 0.0f; data[2].V = 0.0f; + + Gfx_UnlockVb(framebuffer_vb); +} + +static GX2Texture fb; +void Window_AllocFramebuffer(struct Bitmap* bmp, int width, int height) { + fb.surface.width = width; + fb.surface.height = height; + fb.surface.depth = 1; + fb.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D; + fb.surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8; + fb.surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED; + fb.viewNumSlices = 1; + fb.compMap = 0x00010203; + GX2CalcSurfaceSizeAndAlignment(&fb.surface); + GX2InitTextureRegs(&fb); + + fb.surface.image = MEMAllocFromDefaultHeapEx(fb.surface.imageSize, fb.surface.alignment); + bmp->scan0 = (BitmapCol*)Mem_Alloc(width * height, 4, "window pixels"); + bmp->width = width; + bmp->height = height; +} + +static void DrawLauncher(void) { + Gfx_LoadIdentityMatrix(MATRIX_VIEW); + Gfx_LoadIdentityMatrix(MATRIX_PROJECTION); + Gfx_SetDepthTest(false); + + Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED); + Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED); + Gfx_BindTexture(&fb); + Gfx_BindVb(framebuffer_vb); + Gfx_DrawVb_IndexedTris(4); +} + +static void DrawTV(void) { + WHBGfxBeginRenderTV(); + WHBGfxClearColor(0.7f, 0.7f, 0.7f, 1.0f); + DrawLauncher(); + if (keyboardOpen) OnscreenKeyboard_DrawTV(); + WHBGfxFinishRenderTV(); +} + +static void DrawDRC(void) { + WHBGfxBeginRenderDRC(); + WHBGfxClearColor(0.7f, 0.7f, 0.7f, 1.0f); + DrawLauncher(); + if (keyboardOpen) OnscreenKeyboard_DrawDRC(); + WHBGfxFinishRenderDRC(); +} + +void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { + if (launcherTop || Window_Main.Inactive) return; + + struct Bitmap part; + part.scan0 = Bitmap_GetRow(bmp, r.y) + r.x; + part.width = r.width; + part.height = r.height; + Gfx_UpdateTexture(&fb, r.x, r.y, &part, bmp->width, false); + + WHBGfxBeginRender(); + DrawDRC(); + DrawTV(); + WHBGfxFinishRender(); +} + +void Window_FreeFramebuffer(struct Bitmap* bmp) { + MEMFreeToDefaultHeap(fb.surface.image); + Mem_Free(bmp->scan0); +} + + +/*########################################################################################################################* +*-------------------------------------------------------Misc/Other--------------------------------------------------------* +*#########################################################################################################################*/ +void Window_SetTitle(const cc_string* title) { } +void Clipboard_GetText(cc_string* value) { } +void Clipboard_SetText(const cc_string* value) { } + +int Window_GetWindowState(void) { return WINDOW_STATE_FULLSCREEN; } +cc_result Window_EnterFullscreen(void) { return 0; } +cc_result Window_ExitFullscreen(void) { return 0; } +int Window_IsObscured(void) { return 0; } + +void Window_Show(void) { } +void Window_SetSize(int width, int height) { } + +void Window_ShowDialog(const char* title, const char* msg) { + /* TODO implement */ + Platform_LogConst(title); + Platform_LogConst(msg); +} + +cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { + return ERR_NOT_SUPPORTED; +} + +cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { + return ERR_NOT_SUPPORTED; +} + + +/*########################################################################################################################* +*----------------------------------------------------Onscreen keyboard----------------------------------------------------* +*#########################################################################################################################*/ +static FSClient* fs_client; +static nn::swkbd::CreateArg create_arg; +static nn::swkbd::AppearArg appear_arg; + +static char kb_buffer[512]; +static cc_string kb_str = String_FromArray(kb_buffer); +#define UNI_STR_LENGTH 64 + +static int UniString_Length(const char16_t* raw) { + int length = 0; + while (length < UInt16_MaxValue && *raw) { raw++; length++; } + return length; +} + +static void UniString_WriteConst(const char* src, char16_t* dst) { + while (*src) { *dst++ = *src++; } + *dst = '\0'; +} + +static void UniString_WriteString(const cc_string* src, char16_t* dst) { + int len = min(src->length, UNI_STR_LENGTH); + + for (int i = 0; i < len; i++) + { + *dst++ = Convert_CP437ToUnicode(src->buffer[i]); + } + *dst = '\0'; +} + + +void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { + if (keyboardOpen) OnscreenKeyboard_Close(); + char16_t hint[UNI_STR_LENGTH + 1] = { 0 }; + char16_t initial[UNI_STR_LENGTH + 1] = { 0 }; + int mode = args->type & 0xFF; + + kb_str.length = 0; + keyboardOpen = true; + Window_Main.SoftKeyboardFocus = true; + + fs_client = (FSClient *)MEMAllocFromDefaultHeap(sizeof(FSClient)); + FSAddClient(fs_client, FS_ERROR_FLAG_NONE); + + Mem_Set(&create_arg, 0, sizeof(create_arg)); + create_arg.regionType = nn::swkbd::RegionType::Europe; + create_arg.workMemory = MEMAllocFromDefaultHeap(nn::swkbd::GetWorkMemorySize(0)); + create_arg.fsClient = fs_client; + + if (!nn::swkbd::Create(create_arg)) { + Platform_LogConst("nn::swkbd::Create failed"); + return; + } + + nn::swkbd::MuteAllSound(false); + Mem_Set(&appear_arg, 0, sizeof(appear_arg)); + + nn::swkbd::ConfigArg* cfg = &appear_arg.keyboardArg.configArg; + cfg->languageType = nn::swkbd::LanguageType::English; + cfg->okString = args->type & KEYBOARD_FLAG_SEND ? u"Send" : u"OK"; + + if (mode == KEYBOARD_TYPE_INTEGER) { + cfg->keyboardMode = nn::swkbd::KeyboardMode::Numpad; + cfg->numpadCharLeft = '-'; + cfg->numpadCharRight = 0; + } else if (mode == KEYBOARD_TYPE_NUMBER) { + cfg->keyboardMode = nn::swkbd::KeyboardMode::Numpad; + cfg->numpadCharLeft = '-'; + cfg->numpadCharRight = '.'; + } + + nn::swkbd::InputFormArg* ipt = &appear_arg.inputFormArg; + UniString_WriteConst(args->placeholder, hint); + UniString_WriteString(args->text, initial); + ipt->hintText = hint; + ipt->initialText = initial; + + if (mode == KEYBOARD_TYPE_PASSWORD) + ipt->passwordMode = nn::swkbd::PasswordMode::Hide; + + if (!nn::swkbd::AppearInputForm(appear_arg)) { + Platform_LogConst("nn::swkbd::AppearInputForm failed"); + return; + } +} + +static void ProcessKeyboardInput(void) { + char tmpBuffer[NATIVE_STR_LEN]; + cc_string tmp = String_FromArray(tmpBuffer); + + const char16_t* str = nn::swkbd::GetInputFormString(); + if (!str) return; + String_AppendUtf16(&tmp, str, UniString_Length(str)); + + if (String_Equals(&tmp, &kb_str)) return; + String_Copy(&kb_str, &tmp); + Event_RaiseString(&InputEvents.TextChanged, &tmp); +} + +static void OnscreenKeyboard_Update(void) { + nn::swkbd::ControllerInfo controllerInfo; + controllerInfo.vpad = &vpadStatus; + controllerInfo.kpad[0] = kpad_valid[0] ? &kpads[0] : nullptr; + controllerInfo.kpad[1] = kpad_valid[1] ? &kpads[1] : nullptr; + controllerInfo.kpad[2] = kpad_valid[2] ? &kpads[2] : nullptr; + controllerInfo.kpad[3] = kpad_valid[3] ? &kpads[3] : nullptr; + nn::swkbd::Calc(controllerInfo); + + if (nn::swkbd::IsNeedCalcSubThreadFont()) { + nn::swkbd::CalcSubThreadFont(); + } + + if (nn::swkbd::IsNeedCalcSubThreadPredict()) { + nn::swkbd::CalcSubThreadPredict(); + } + ProcessKeyboardInput(); + + if (nn::swkbd::IsDecideOkButton(nullptr)) { + Input_SetPressed(CCKEY_ENTER); + Input_SetReleased(CCKEY_ENTER); + OnscreenKeyboard_Close(); + return; + } + + if (nn::swkbd::IsDecideCancelButton(nullptr)) { + OnscreenKeyboard_Close(); + return; + } +} + +static void OnscreenKeyboard_DrawTV(void) { + nn::swkbd::DrawTV(); +} + +static void OnscreenKeyboard_DrawDRC(void) { + nn::swkbd::DrawDRC(); +} + + +void OnscreenKeyboard_SetText(const cc_string* text) { } +void OnscreenKeyboard_Draw2D(Rect2D* r, struct Bitmap* bmp) { } +void OnscreenKeyboard_Draw3D(void) { } + +void OnscreenKeyboard_Close(void) { + if (!keyboardOpen) return; + keyboardOpen = false; + Window_Main.SoftKeyboardFocus = false; + + nn::swkbd::DisappearInputForm(); + nn::swkbd::Destroy(); + MEMFreeToDefaultHeap(create_arg.workMemory); + + FSDelClient(fs_client, FS_ERROR_FLAG_NONE); + MEMFreeToDefaultHeap(fs_client); +} +#endif |