mirror of https://github.com/mgba-emu/mgba.git
mGUI: Initial OSK support
This commit is contained in:
parent
926e8fcccb
commit
4ba921ccc5
|
@ -14,6 +14,9 @@ CXX_GUARD_START
|
|||
#include <mgba/core/input.h>
|
||||
#include <mgba-util/vector.h>
|
||||
|
||||
#define MAX_KEYBOARD_LEN 256
|
||||
#define MAX_KEYBOARD_TITLE_LEN 128
|
||||
|
||||
struct GUIFont;
|
||||
|
||||
enum GUIInput {
|
||||
|
@ -40,6 +43,11 @@ enum GUICursorState {
|
|||
GUI_CURSOR_DRAGGING
|
||||
};
|
||||
|
||||
enum GUIKeyboardStatus {
|
||||
GUI_KEYBOARD_DONE = 0,
|
||||
GUI_KEYBOARD_CANCEL,
|
||||
};
|
||||
|
||||
enum {
|
||||
BATTERY_EMPTY = 0,
|
||||
BATTERY_LOW = 25,
|
||||
|
@ -57,6 +65,13 @@ struct GUIBackground {
|
|||
void (*draw)(struct GUIBackground*, void* context);
|
||||
};
|
||||
|
||||
struct GUIKeyboardParams {
|
||||
char title[MAX_KEYBOARD_TITLE_LEN];
|
||||
char result[MAX_KEYBOARD_LEN];
|
||||
size_t maxLen;
|
||||
bool multiline;
|
||||
};
|
||||
|
||||
struct GUIParams {
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
|
@ -70,6 +85,7 @@ struct GUIParams {
|
|||
int (*batteryState)(void);
|
||||
void (*guiPrepare)(void);
|
||||
void (*guiFinish)(void);
|
||||
enum GUIKeyboardStatus (*getText)(struct GUIKeyboardParams*);
|
||||
|
||||
// State
|
||||
struct mInputMap keyMap;
|
||||
|
@ -87,6 +103,8 @@ void GUIPollInput(struct GUIParams* params, uint32_t* newInput, uint32_t* heldIn
|
|||
enum GUICursorState GUIPollCursor(struct GUIParams* params, unsigned* x, unsigned* y);
|
||||
void GUIInvalidateKeys(struct GUIParams* params);
|
||||
|
||||
void GUIKeyboardParamsInit(struct GUIKeyboardParams*);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -797,6 +797,22 @@ static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* rig
|
|||
}
|
||||
}
|
||||
|
||||
static enum GUIKeyboardStatus _keyboardRun(struct GUIKeyboardParams* keyboard) {
|
||||
SwkbdState swkbd;
|
||||
swkbdInit(&swkbd, SWKBD_TYPE_NORMAL, 2, keyboard->maxLen);
|
||||
swkbdSetInitialText(&swkbd, keyboard->result);
|
||||
if (keyboard->multiline) {
|
||||
swkbdSetFeatures(&swkbd, SWKBD_MULTILINE);
|
||||
}
|
||||
|
||||
SwkbdButton button = swkbdInputText(&swkbd, keyboard->result, sizeof( keyboard->result));
|
||||
if (button == SWKBD_BUTTON_CONFIRM) {
|
||||
return GUI_KEYBOARD_DONE;
|
||||
} else {
|
||||
return GUI_KEYBOARD_CANCEL;
|
||||
}
|
||||
}
|
||||
|
||||
THREAD_ENTRY _core2Test(void* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
|
@ -892,6 +908,7 @@ int main() {
|
|||
_pollInput, _pollCursor,
|
||||
_batteryState,
|
||||
_guiPrepare, _guiFinish,
|
||||
_keyboardRun,
|
||||
},
|
||||
.keySources = (struct GUIInputKeys[]) {
|
||||
{
|
||||
|
|
|
@ -22,6 +22,7 @@ set(OS_LIB -lvita2d -l${M_LIBRARY}
|
|||
-lSceCtrl_stub
|
||||
-lSceDisplay_stub
|
||||
-lSceGxm_stub
|
||||
-lSceIme_stub
|
||||
-lSceMotion_stub
|
||||
-lScePgf_stub
|
||||
-lScePhotoExport_stub
|
||||
|
|
|
@ -11,10 +11,12 @@
|
|||
#include <mgba-util/gui/font.h>
|
||||
#include <mgba-util/gui/file-select.h>
|
||||
#include <mgba-util/gui/menu.h>
|
||||
#include <mgba-util/string.h>
|
||||
|
||||
#include <psp2/apputil.h>
|
||||
#include <psp2/ctrl.h>
|
||||
#include <psp2/display.h>
|
||||
#include <psp2/ime_dialog.h>
|
||||
#include <psp2/kernel/processmgr.h>
|
||||
#include <psp2/kernel/threadmgr.h>
|
||||
#include <psp2/power.h>
|
||||
|
@ -36,6 +38,7 @@ static void _drawStart(void) {
|
|||
|
||||
static void _drawEnd(void) {
|
||||
vita2d_end_drawing();
|
||||
vita2d_common_dialog_update();
|
||||
vita2d_swap_buffers();
|
||||
}
|
||||
|
||||
|
@ -81,6 +84,66 @@ static int _batteryState(void) {
|
|||
return state | charge;
|
||||
}
|
||||
|
||||
static enum GUIKeyboardStatus _keyboardRun(struct GUIKeyboardParams* keyboard) {
|
||||
SceImeDialogParam params;
|
||||
sceImeDialogParamInit(¶ms);
|
||||
params.supportedLanguages = 0x0001FFFF;
|
||||
params.languagesForced = SCE_TRUE;
|
||||
params.type = SCE_IME_TYPE_DEFAULT;
|
||||
params.option = 0;
|
||||
if (keyboard->multiline) {
|
||||
params.option = SCE_IME_OPTION_MULTILINE;
|
||||
}
|
||||
params.dialogMode = SCE_IME_DIALOG_DIALOG_MODE_WITH_CANCEL;
|
||||
params.maxTextLength = keyboard->maxLen;
|
||||
params.title = calloc(sizeof(SceWChar16), MAX_KEYBOARD_TITLE_LEN + 1);
|
||||
params.inputTextBuffer = calloc(sizeof(SceWChar16), keyboard->maxLen + 1);
|
||||
params.initialText = calloc(sizeof(SceWChar16), keyboard->maxLen + 1);
|
||||
|
||||
uint16_t* utf16Buffer = params.initialText;
|
||||
char* utf8Buffer = keyboard->result;
|
||||
size_t i = keyboard->maxLen;
|
||||
while (i > 0 && *utf8Buffer) {
|
||||
uint32_t unichar = utf8Char((const char**) &utf8Buffer, &i);
|
||||
utf16Buffer += toUtf16(unichar, utf16Buffer);
|
||||
}
|
||||
|
||||
utf16Buffer = params.title;
|
||||
utf8Buffer = keyboard->title;
|
||||
i = MAX_KEYBOARD_TITLE_LEN;
|
||||
while (i > 0 && *utf8Buffer) {
|
||||
uint32_t unichar = utf8Char((const char**) &utf8Buffer, &i);
|
||||
utf16Buffer += toUtf16(unichar, utf16Buffer);
|
||||
}
|
||||
|
||||
sceImeDialogInit(¶ms);
|
||||
SceCommonDialogStatus status = SCE_COMMON_DIALOG_STATUS_RUNNING;
|
||||
while (status == SCE_COMMON_DIALOG_STATUS_RUNNING) {
|
||||
_drawStart();
|
||||
status = sceImeDialogGetStatus();
|
||||
_drawEnd();
|
||||
}
|
||||
|
||||
SceImeDialogResult result;
|
||||
memset(&result, 0, sizeof(SceImeDialogResult));
|
||||
sceImeDialogGetResult(&result);
|
||||
sceImeDialogTerm();
|
||||
|
||||
utf16Buffer = params.inputTextBuffer;
|
||||
utf8Buffer = keyboard->result;
|
||||
i = keyboard->maxLen;
|
||||
while (i > 0 && *utf16Buffer) {
|
||||
uint32_t unichar = utf16Char((const uint16_t**) &utf16Buffer, &i);
|
||||
utf8Buffer += toUtf8(unichar, utf8Buffer);
|
||||
}
|
||||
utf8Buffer[0] = 0;
|
||||
|
||||
free(params.initialText);
|
||||
free(params.inputTextBuffer);
|
||||
|
||||
return result.button == SCE_IME_DIALOG_BUTTON_ENTER ? GUI_KEYBOARD_DONE : GUI_KEYBOARD_CANCEL;
|
||||
}
|
||||
|
||||
int main() {
|
||||
vita2d_init();
|
||||
struct GUIFont* font = GUIFontCreate();
|
||||
|
@ -92,6 +155,7 @@ int main() {
|
|||
_pollInput, _pollCursor,
|
||||
_batteryState,
|
||||
0, 0,
|
||||
_keyboardRun,
|
||||
},
|
||||
.configExtra = (struct GUIMenuItem[]) {
|
||||
{
|
||||
|
@ -167,6 +231,7 @@ int main() {
|
|||
sceCtrlSetSamplingModeExt(SCE_CTRL_MODE_ANALOG_WIDE);
|
||||
sceSysmoduleLoadModule(SCE_SYSMODULE_PHOTO_EXPORT);
|
||||
sceSysmoduleLoadModule(SCE_SYSMODULE_APPUTIL);
|
||||
sceSysmoduleLoadModule(SCE_SYSMODULE_IME);
|
||||
|
||||
mGUIInit(&runner, "psvita");
|
||||
|
||||
|
|
|
@ -674,6 +674,24 @@ static void _guiFinish(void) {
|
|||
GUIFontDrawSubmit(font);
|
||||
}
|
||||
|
||||
static enum GUIKeyboardStatus _keyboardRun(struct GUIKeyboardParams* keyboard) {
|
||||
SwkbdConfig swkbd;
|
||||
swkbdCreate(&swkbd, 0);
|
||||
swkbdConfigMakePresetDefault(&swkbd);
|
||||
swkbdConfigSetStringLenMax(&swkbd, keyboard->maxLen);
|
||||
swkbdConfigSetInitialText(&swkbd, keyboard->result);
|
||||
swkbdConfigSetHeaderText(&swkbd, keyboard->title);
|
||||
swkbdConfigSetReturnButtonFlag(&swkbd, keyboard->multiline);
|
||||
|
||||
Result rc = swkbdShow(&swkbd, keyboard->result, sizeof(keyboard->result));
|
||||
swkbdClose(&swkbd);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
return GUI_KEYBOARD_DONE;
|
||||
} else {
|
||||
return GUI_KEYBOARD_CANCEL;
|
||||
}
|
||||
}
|
||||
|
||||
static void glInit(void) {
|
||||
glViewport(0, 1080 - vheight, vwidth, vheight);
|
||||
glClearColor(0.f, 0.f, 0.f, 1.f);
|
||||
|
@ -865,6 +883,7 @@ int main(int argc, char* argv[]) {
|
|||
_pollInput, _pollCursor,
|
||||
_batteryState,
|
||||
_guiPrepare, _guiFinish,
|
||||
_keyboardRun,
|
||||
},
|
||||
.keySources = (struct GUIInputKeys[]) {
|
||||
{
|
||||
|
|
|
@ -72,3 +72,10 @@ void GUIInvalidateKeys(struct GUIParams* params) {
|
|||
params->inputHistory[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GUIKeyboardParamsInit(struct GUIKeyboardParams* keyboard) {
|
||||
memset(keyboard->title, 0, sizeof(keyboard->title));
|
||||
memset(keyboard->result, 0, sizeof(keyboard->result));
|
||||
keyboard->maxLen = sizeof(keyboard->result);
|
||||
keyboard->multiline = false;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue