mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-27 07:12:40 +02:00
Initial SwkbdInline impl, minor swkbd adjustments.
This commit is contained in:
parent
06733c4750
commit
2900622cb5
@ -40,6 +40,13 @@ typedef enum {
|
||||
SwkbdTextDrawType_DownloadCode = 2, ///< Used by \ref swkbdConfigMakePresetDownloadCode on 5.0.0+. Enables using \ref SwkbdArgV7 unk_x3e0.
|
||||
} SwkbdTextDrawType;
|
||||
|
||||
/// SwkbdInline Interactive input storage request ID.
|
||||
typedef enum {
|
||||
SwkbdRequestCommand_Finalize = 0x4,
|
||||
SwkbdRequestCommand_SetCustomizeDic = 0x7,
|
||||
SwkbdRequestCommand_Calc = 0xA,
|
||||
} SwkbdRequestCommand;
|
||||
|
||||
typedef SwkbdTextCheckResult (*SwkbdTextCheckCb)(char* tmp_string, size_t tmp_string_size); /// TextCheck callback set by \ref swkbdConfigSetTextCheckCallback, for validating the input string when the swkbd ok-button is pressed. This buffer contains an UTF-8 string. This callback should validate the input string, then return a \ref SwkbdTextCheckResult indicating success/failure. On failure, this function must write an error message to the tmp_string buffer, which will then be displayed by swkbd.
|
||||
|
||||
/// Base swkbd arg struct.
|
||||
@ -93,6 +100,71 @@ typedef struct {
|
||||
u8 unk_x0[0x64];
|
||||
} SwkbdDictWord;
|
||||
|
||||
typedef struct {
|
||||
u32 unk_x0;
|
||||
u8 mode; ///< Controls the LibAppletMode when launching the applet. Non-zero indicates LibAppletMode_Background, otherwise LibAppletMode_Unknown3
|
||||
u8 unk_x5; ///< Only set on 5.0.0+.
|
||||
u8 pad[2];
|
||||
} SwkbdInitializeArg;
|
||||
|
||||
typedef struct {
|
||||
u32 unk_x0;
|
||||
u64 unk_x4;
|
||||
u64 unk_xc;
|
||||
u8 unk_x14[0x6];
|
||||
u8 unk_x1a;
|
||||
u8 unk_x1b;
|
||||
u32 unk_x1c;
|
||||
s32 unk_x20;
|
||||
s32 unk_x24;
|
||||
u64 unk_x28;
|
||||
u8 unk_x30;
|
||||
u8 unk_x31[0x17];
|
||||
} SwkbdAppearArg;
|
||||
|
||||
typedef struct {
|
||||
u32 unk_x0;
|
||||
u16 size; ///< Size of this struct.
|
||||
u8 unk_x6;
|
||||
u8 unk_x7;
|
||||
u64 flags;
|
||||
SwkbdInitializeArg initArg; ///< Flags bitmask 0x1.
|
||||
float volume; ///< Flags bitmask 0x2.
|
||||
s32 cursorPos; ///< Flags bitmask 0x10.
|
||||
SwkbdAppearArg appearArg;
|
||||
u8 unk_x68[0x3d4];
|
||||
u8 utf8Mode; ///< Flags bitmask 0x20.
|
||||
u8 unk_x43d;
|
||||
u8 enableBackspace; ///< Flags bitmask 0x8000. Added with 5.x.
|
||||
u8 unk_x43f[3];
|
||||
u8 keytopAsFloating; ///< Flags bitmask 0x200.
|
||||
u8 footerScalable; ///< Flags bitmask 0x100.
|
||||
u8 alphaEnabledInInputMode; ///< Flags bitmask 0x200.
|
||||
u8 inputModeFadeType; ///< Flags bitmask 0x100.
|
||||
u8 disableTouch; ///< Flags bitmask 0x200.
|
||||
u8 disableUSBKeyboard; ///< Flags bitmask 0x800.
|
||||
u8 unk_x448[5];
|
||||
u16 unk_x44d;
|
||||
u8 unk_x44f;
|
||||
float keytopScale0; ///< Flags bitmask 0x200.
|
||||
float keytopScale1; ///< Flags bitmask 0x200.
|
||||
float keytopTranslate0; ///< Flags bitmask 0x200.
|
||||
float keytopTranslate1; ///< Flags bitmask 0x200.
|
||||
float keytopBgAlpha; ///< Flags bitmask 0x100.
|
||||
float unk_x464;
|
||||
float balloonScale; ///< Flags bitmask 0x200.
|
||||
float unk_x46c;
|
||||
u64 unk_x470[4];
|
||||
u8 unk_x490[0x10];
|
||||
} PACKED SwkbdInlineCalcArg;
|
||||
|
||||
/// InlineKeyboard
|
||||
typedef struct {
|
||||
u32 version;
|
||||
AppletHolder holder;
|
||||
SwkbdInlineCalcArg calcArg;
|
||||
} SwkbdInline;
|
||||
|
||||
/**
|
||||
* @brief Creates a SwkbdConfig struct.
|
||||
* @param c SwkbdConfig struct.
|
||||
@ -214,3 +286,30 @@ void swkbdConfigSetTextCheckCallback(SwkbdConfig* c, SwkbdTextCheckCb cb);
|
||||
*/
|
||||
Result swkbdShow(SwkbdConfig* c, char* out_string, size_t out_string_size);
|
||||
|
||||
/**
|
||||
* @brief Creates a SwkbdInline object.
|
||||
* @note This is essentially an asynchronous version of the regular swkbd.
|
||||
* @param s SwkbdInline object.
|
||||
*/
|
||||
Result swkbdInlineCreate(SwkbdInline* s);
|
||||
|
||||
/**
|
||||
* @brief Closes a SwkbdInline object. If the applet is running, this will tell the applet to exit, then wait for the applet to exit + applet exit handling.
|
||||
* @param s SwkbdInline object.
|
||||
*/
|
||||
Result swkbdInlineClose(SwkbdInline* s);
|
||||
|
||||
/**
|
||||
* @brief Launches the applet with the SwkbdInline object.
|
||||
* @param s SwkbdInline object.
|
||||
*/
|
||||
Result swkbdInlineLaunch(SwkbdInline* s);
|
||||
|
||||
/**
|
||||
* @brief Handles updating SwkbdInline state, this should be called periodically.
|
||||
* @note Handles applet exit if needed, and also sends the \ref SwkbdInlineCalcArg to the applet if needed. Hence, this should be called at some point after writing to \ref SwkbdInlineCalcArg.
|
||||
* @note Handles applet Interactive storage output when needed.
|
||||
* @param s SwkbdInline object.
|
||||
*/
|
||||
Result swkbdInlineUpdate(SwkbdInline* s);
|
||||
|
||||
|
@ -39,25 +39,29 @@ static void _swkbdConfigClear(SwkbdConfig* c) {
|
||||
memset(c->arg.unk_x3e0, 0xff, sizeof(c->arg.unk_x3e0));
|
||||
}
|
||||
|
||||
static void _swkbdInitVersion(u32* version) {
|
||||
*version=0x5;//1.0.0+ version
|
||||
if (kernelAbove500()) {
|
||||
*version = 0x50009;
|
||||
}
|
||||
else if (kernelAbove400()) {
|
||||
*version = 0x40008;
|
||||
}
|
||||
else if (kernelAbove300()) {
|
||||
*version = 0x30007;
|
||||
}
|
||||
else if (kernelAbove200()) {
|
||||
*version = 0x10006;
|
||||
}
|
||||
}
|
||||
|
||||
Result swkbdCreate(SwkbdConfig* c, s32 max_dictwords) {
|
||||
Result rc=0;
|
||||
|
||||
memset(c, 0, sizeof(SwkbdConfig));
|
||||
_swkbdConfigClear(c);
|
||||
|
||||
c->version=0x5;//1.0.0+ version
|
||||
if (kernelAbove500()) {
|
||||
c->version = 0x50009;
|
||||
}
|
||||
else if (kernelAbove400()) {
|
||||
c->version = 0x40008;
|
||||
}
|
||||
else if (kernelAbove300()) {
|
||||
c->version = 0x30007;
|
||||
}
|
||||
else if (kernelAbove200()) {
|
||||
c->version = 0x10006;
|
||||
}
|
||||
_swkbdInitVersion(&c->version);
|
||||
|
||||
c->workbuf_size = 0x1000;
|
||||
if (max_dictwords > 0 && max_dictwords <= 0x3e8) c->max_dictwords = max_dictwords;
|
||||
@ -310,3 +314,120 @@ Result swkbdShow(SwkbdConfig* c, char* out_string, size_t out_string_size) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
static Result _swkbdSendRequest(SwkbdInline* s, u32 RequestCommand, const void* buffer, size_t size) {
|
||||
Result rc=0;
|
||||
AppletStorage storage;
|
||||
|
||||
rc = appletCreateStorage(&storage, size+sizeof(u32));
|
||||
if (R_FAILED(rc)) return rc;
|
||||
|
||||
rc = appletStorageWrite(&storage, 0, &RequestCommand, sizeof(RequestCommand));
|
||||
if (R_SUCCEEDED(rc) && buffer!=NULL) rc = appletStorageWrite(&storage, sizeof(RequestCommand), buffer, size);
|
||||
if (R_FAILED(rc)) {
|
||||
appletStorageClose(&storage);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return appletHolderPushInteractiveInData(&s->holder, &storage);
|
||||
}
|
||||
|
||||
Result swkbdInlineCreate(SwkbdInline* s) {
|
||||
memset(s, 0, sizeof(SwkbdInline));
|
||||
|
||||
_swkbdInitVersion(&s->version);
|
||||
|
||||
s->calcArg.unk_x0 = 0x30000;
|
||||
s->calcArg.size = sizeof(s->calcArg);
|
||||
|
||||
//if (s->version >= 0x50009) s->calcArg.initArg.unk_x5 = 0x1;//Set in a separate init func by official sw on 5.0.0+.
|
||||
|
||||
s->calcArg.volume = 1.0f;
|
||||
s->calcArg.appearArg.unk_x0 = 0x2;
|
||||
s->calcArg.unk_x6 = 1;
|
||||
s->calcArg.unk_x7 = 1;
|
||||
s->calcArg.appearArg.unk_x20 = -1;
|
||||
s->calcArg.appearArg.unk_x24 = -1;
|
||||
s->calcArg.appearArg.unk_x30 = 1;
|
||||
|
||||
s->calcArg.enableBackspace = 1;
|
||||
s->calcArg.unk_x43f[0] = 1;
|
||||
s->calcArg.footerScalable = 1;
|
||||
s->calcArg.inputModeFadeType = 1;
|
||||
|
||||
s->calcArg.keytopScale0 = 1.0f;
|
||||
s->calcArg.keytopScale1 = 1.0f;
|
||||
s->calcArg.keytopBgAlpha = 1.0f;
|
||||
s->calcArg.unk_x464 = 1.0f;
|
||||
s->calcArg.balloonScale = 1.0f;
|
||||
s->calcArg.unk_x46c = 1.0f;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Result swkbdInlineClose(SwkbdInline* s) {
|
||||
Result rc=0;
|
||||
|
||||
if (appletHolderActive(&s->holder))
|
||||
{
|
||||
_swkbdSendRequest(s, SwkbdRequestCommand_Finalize, NULL, 0);//Finalize cmd
|
||||
|
||||
appletHolderJoin(&s->holder);
|
||||
|
||||
LibAppletExitReason reason = appletHolderGetExitReason(&s->holder);
|
||||
|
||||
if (reason == LibAppletExitReason_Canceled) {
|
||||
rc = MAKERESULT(Module_Libnx, LibnxError_LibAppletBadExit);
|
||||
}
|
||||
else if (reason == LibAppletExitReason_Abnormal || reason == LibAppletExitReason_Unexpected) {
|
||||
rc = MAKERESULT(Module_Libnx, LibnxError_LibAppletBadExit);
|
||||
}
|
||||
|
||||
appletHolderClose(&s->holder);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result swkbdInlineLaunch(SwkbdInline* s) {
|
||||
Result rc=0;
|
||||
|
||||
rc = appletCreateLibraryApplet(&s->holder, AppletId_swkbd, s->calcArg.initArg.mode!=0 ? LibAppletMode_Background : LibAppletMode_Unknown3);
|
||||
if (R_FAILED(rc)) return rc;
|
||||
|
||||
LibAppletArgs commonargs;
|
||||
libappletArgsCreate(&commonargs, s->version);
|
||||
rc = libappletArgsPush(&commonargs, &s->holder);
|
||||
|
||||
if (R_SUCCEEDED(rc)) rc = libappletPushInData(&s->holder, &s->calcArg.initArg, sizeof(s->calcArg.initArg));
|
||||
|
||||
if (R_SUCCEEDED(rc)) rc = appletHolderStart(&s->holder);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result swkbdInlineUpdate(SwkbdInline* s) {
|
||||
Result rc=0;
|
||||
AppletStorage storage;
|
||||
|
||||
//TODO: 'Normalize' floats.
|
||||
|
||||
if (appletHolderCheckFinished(&s->holder)) {
|
||||
appletHolderJoin(&s->holder);
|
||||
appletHolderClose(&s->holder);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->calcArg.flags) {
|
||||
rc = _swkbdSendRequest(s, SwkbdRequestCommand_Calc, &s->calcArg, sizeof(s->calcArg));
|
||||
s->calcArg.flags = 0;
|
||||
if (R_FAILED(rc)) return rc;
|
||||
}
|
||||
|
||||
while(R_SUCCEEDED(appletHolderPopInteractiveOutData(&s->holder, &storage))) {
|
||||
//TODO: Process storage content.
|
||||
appletStorageClose(&storage);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user