swkbd: Added proper support for using SwkbdInlineMode_UserDisplay.

This commit is contained in:
yellows8 2020-06-11 22:40:14 -04:00
parent 29dd63e5db
commit 857e2f5c4d
No known key found for this signature in database
GPG Key ID: 0AF90DA3F1E60E43
2 changed files with 81 additions and 6 deletions

View File

@ -92,7 +92,7 @@ typedef enum {
/// Value for \ref SwkbdInitializeArg mode. Controls the LibAppletMode when launching the applet.
typedef enum {
SwkbdInlineMode_UserDisplay = 0, ///< LibAppletMode_Unknown3. This is the default. The user-process must handle displaying the swkbd gfx on the screen. Attempting to get the swkbd gfx data for this currently throws an error (unknown why), SwkbdInlineMode_AppletDisplay should be used instead.
SwkbdInlineMode_UserDisplay = 0, ///< LibAppletMode_BackgroundIndirect. This is the default. The user-process must handle displaying the swkbd gfx on the screen, by loading the image with \ref swkbdInlineGetImage.
SwkbdInlineMode_AppletDisplay = 1, ///< LibAppletMode_Background. The applet will handle displaying gfx on the screen.
} SwkbdInlineMode;
@ -597,6 +597,35 @@ Result swkbdInlineClose(SwkbdInline* s);
*/
Result swkbdInlineLaunch(SwkbdInline* s);
/**
* @brief GetWindowSize
* @param[out] width Output width.
* @param[out] height Output height.
*/
NX_CONSTEXPR void swkbdInlineGetWindowSize(s32 *width, s32 *height) {
*width = 1280;
*height = 720;
}
/**
* @brief GetImageMemoryRequirement
* @note Wrapper for \ref viGetIndirectLayerImageRequiredMemoryInfo.
* @param[out] out_size Output size.
* @param[out] out_alignment Output alignment.
*/
Result swkbdInlineGetImageMemoryRequirement(u64 *out_size, u64 *out_alignment);
/**
* @brief GetImage
* @note Only available with ::SwkbdInlineMode_UserDisplay.
* @note For width/height, see \ref swkbdInlineGetWindowSize.
* @param s SwkbdInline object.
* @param[out] buffer Output RGBA8 image buffer, this must use the alignment from \ref swkbdInlineGetImageMemoryRequirement.
* @param[in] size Output buffer size, this must match the size from \ref swkbdInlineGetImageMemoryRequirement.
* @param[out] data_available Whether data is available.
*/
Result swkbdInlineGetImage(SwkbdInline* s, void* buffer, u64 size, bool *data_available);
/**
* @brief Same as \ref swkbdInlineLaunch, except mode and unk_x5 for \ref SwkbdInitializeArg are set to the input params.
* @param s SwkbdInline object.

View File

@ -3,6 +3,7 @@
#include <math.h>
#include "libapplet_internal.h"
#include "applets/swkbd.h"
#include "services/vi.h"
#include "runtime/hosversion.h"
#include "runtime/util/utf.h"
@ -484,6 +485,17 @@ Result swkbdInlineClose(SwkbdInline* s) {
return rc;
}
static bool _swkbdInlineHandleFinished(SwkbdInline* s) {
bool ret = appletHolderCheckFinished(&s->holder);
if (ret) {
appletHolderJoin(&s->holder);
appletHolderClose(&s->holder);
s->state = SwkbdState_Inactive;
}
return ret;
}
static Result _swkbdInlineLaunch(SwkbdInline* s, SwkbdInitializeArg *initArg) {
Result rc=0;
@ -526,6 +538,44 @@ Result swkbdInlineLaunchForLibraryApplet(SwkbdInline* s, u8 mode, u8 unk_x5) {
return _swkbdInlineLaunch(s, &initArg);
}
Result swkbdInlineGetImageMemoryRequirement(u64 *out_size, u64 *out_alignment) {
s32 width=0, height=0;
swkbdInlineGetWindowSize(&width, &height);
return viGetIndirectLayerImageRequiredMemoryInfo(width, height, out_size, out_alignment);
}
Result swkbdInlineGetImage(SwkbdInline* s, void* buffer, u64 size, bool *data_available) {
Result rc=0;
u64 out_size=0, out_alignment=0;
s32 width=0, height=0;
u64 handle=0;
if (!buffer || !size) return MAKERESULT(Module_Libnx, LibnxError_BadInput);
if (_swkbdInlineHandleFinished(s)) {
data_available = false;
return 0;
}
rc = swkbdInlineGetImageMemoryRequirement(&out_size, &out_alignment);
if (R_SUCCEEDED(rc)) {
if (out_size != size || (uintptr_t)buffer & (out_alignment-1))
rc = MAKERESULT(Module_Libnx, LibnxError_BadInput);
}
swkbdInlineGetWindowSize(&width, &height);
if (R_SUCCEEDED(rc)) rc = appletHolderGetIndirectLayerConsumerHandle(&s->holder, &handle);
if (R_SUCCEEDED(rc)) rc = viGetIndirectLayerImageMap(buffer, size, width, height, handle, NULL, NULL);
if (R_SUCCEEDED(rc)) *data_available = true;
else if (R_VALUE(rc) == MAKERESULT(114, 11)) {
*data_available = false;
rc = 0;
}
return rc;
}
static void _swkbdProcessReply(SwkbdInline* s, SwkbdReplyType ReplyType, size_t size) {
size_t stringendoff_utf8 = 0x7D4;
size_t stringendoff_utf16 = 0x3EC;
@ -664,11 +714,7 @@ Result swkbdInlineUpdate(SwkbdInline* s, SwkbdState* out_state) {
}
swkbdInlineSetInputModeFadeType(s, fadetype);
if (appletHolderCheckFinished(&s->holder)) {
appletHolderJoin(&s->holder);
appletHolderClose(&s->holder);
s->state = SwkbdState_Inactive;
if (_swkbdInlineHandleFinished(s)) {
if (out_state) *out_state = s->state;
return 0;
}