From 3d4f61735ad8515dfb3e9dc0c0c7568babbdec33 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Sun, 14 Jun 2020 00:03:19 -0400 Subject: [PATCH] swkbd: Updated for 10.x and added: swkbdInlineGetMaxHeight, swkbdInlineGetTouchRectangles, swkbdInlineIsUsedTouchPointByKeyboard. --- nx/include/switch/applets/swkbd.h | 42 +++++++++++++++-- nx/source/applets/swkbd.c | 77 +++++++++++++++++++++++++++++-- 2 files changed, 112 insertions(+), 7 deletions(-) diff --git a/nx/include/switch/applets/swkbd.h b/nx/include/switch/applets/swkbd.h index 4a48472a..6b191c83 100644 --- a/nx/include/switch/applets/swkbd.h +++ b/nx/include/switch/applets/swkbd.h @@ -27,6 +27,7 @@ typedef enum { SwkbdType_ZhHant = 6, ///< Chinese Traditional keyboard only. SwkbdType_Korean = 7, ///< Korean keyboard only. SwkbdType_All = 8, ///< All language keyboards. + SwkbdType_Unknown9 = 9, ///< Unknown } SwkbdType; /// Bitmask for SwkbdArgCommon::keySetDisableBitmask. This disables keys on the keyboard when the corresponding bit(s) are set. @@ -88,6 +89,7 @@ typedef enum { SwkbdState_TextAvailable = 0x3, ///< Text is available since a ChangedString* reply was received. SwkbdState_Submitted = 0x4, ///< The user pressed the ok-button, submitting the text and closing the applet. SwkbdState_Unknown5 = 0x5, + SwkbdState_Unknown6 = 0x6, } SwkbdState; /// Value for \ref SwkbdInitializeArg mode. Controls the LibAppletMode when launching the applet. @@ -184,6 +186,14 @@ typedef struct { u32 version; } SwkbdConfig; +/// Rect +typedef struct { + s16 x; ///< X + s16 y; ///< Y + s16 width; ///< Width + s16 height; ///< Height +} SwkbdRect; + /// InitializeArg for SwkbdInline. typedef struct { u32 unk_x0; @@ -203,7 +213,7 @@ typedef struct { s32 unk_x20; s32 unk_x24; u8 returnButtonFlag; ///< Controls whether the Return button is enabled, for newlines input. 0 = disabled, non-zero = enabled. - u8 unk_x29; + u8 unk_x29; ///< [10.0.0+] When value 1-2, \ref swkbdInlineAppear / \ref swkbdInlineAppearEx will set keytopAsFloating=0 and footerScalable=1. u8 unk_x2a; u8 unk_x2b; u32 flags; ///< Bitmask 0x4: unknown. @@ -231,7 +241,7 @@ typedef struct { u8 alphaEnabledInInputMode; ///< Flags bitmask 0x100. u8 inputModeFadeType; ///< Flags bitmask 0x100. u8 disableTouch; ///< Flags bitmask 0x200. - u8 disableUSBKeyboard; ///< Flags bitmask 0x800. + u8 disableHardwareKeyboard; ///< Flags bitmask 0x800. u8 unk_x468[5]; u8 unk_x46d; u8 unk_x46e; @@ -634,6 +644,28 @@ Result swkbdInlineGetImageMemoryRequirement(u64 *out_size, u64 *out_alignment); */ Result swkbdInlineGetImage(SwkbdInline* s, void* buffer, u64 size, bool *data_available); +/** + * @brief Gets the image max height, relative to the bottom of the screen. + * @param s SwkbdInline object. + */ +s32 swkbdInlineGetMaxHeight(SwkbdInline* s); + +/** + * @brief GetTouchRectangles. Returns number of valid Rects: 1 for only keytop, 2 for keytop/footer. + * @param s SwkbdInline object. + * @param[out] keytop \ref SwkbdRect for keytop. Optional, can be NULL. + * @param[out] footer \ref SwkbdRect for footer. Optional, can be NULL. + */ +s32 swkbdInlineGetTouchRectangles(SwkbdInline* s, SwkbdRect *keytop, SwkbdRect *footer); + +/** + * @brief Gets whether the input x/y are within the output from \ref swkbdInlineGetTouchRectangles. + * @param s SwkbdInline object. + * @param[out] x X + * @param[out] y Y + */ +bool swkbdInlineIsUsedTouchPointByKeyboard(SwkbdInline* s, s32 x, s32 y); + /** * @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. @@ -893,6 +925,7 @@ void swkbdInlineSetFooterBgAlpha(SwkbdInline* s, float alpha); /** * @brief Sets gfx scaling. Configures KeytopScale* and BalloonScale based on the input value. * @note \ref swkbdInlineUpdate must be called at some point afterwards for this to take affect. + * @note The BalloonScale is not updated when \ref SwkbdState is above ::SwkbdState_Initialized. * @param s SwkbdInline object. * @param scale Scale */ @@ -910,6 +943,7 @@ void swkbdInlineSetKeytopTranslate(SwkbdInline* s, float x, float y); /** * @brief Sets KeytopAsFloating. * @note \ref swkbdInlineUpdate must be called at some point afterwards for this to take affect. + * @note Not avilable when \ref SwkbdState is above ::SwkbdState_Initialized. * @param s SwkbdInline object. * @param flag Flag */ @@ -932,12 +966,12 @@ void swkbdInlineSetFooterScalable(SwkbdInline* s, bool flag); void swkbdInlineSetTouchFlag(SwkbdInline* s, bool flag); /** - * @brief Sets whether USB-keyboard is enabled. The default is enabled. + * @brief Sets whether Hardware-keyboard is enabled. The default is enabled. * @note \ref swkbdInlineUpdate must be called at some point afterwards for this to take affect. * @param s SwkbdInline object. * @param flag Flag */ -void swkbdInlineSetUSBKeyboardFlag(SwkbdInline* s, bool flag); +void swkbdInlineSetHardwareKeyboardFlag(SwkbdInline* s, bool flag); /** * @brief Sets whether DirectionalButtonAssign is enabled. The default is disabled. diff --git a/nx/source/applets/swkbd.c b/nx/source/applets/swkbd.c index 0e845ed3..d35db07f 100644 --- a/nx/source/applets/swkbd.c +++ b/nx/source/applets/swkbd.c @@ -576,6 +576,71 @@ Result swkbdInlineGetImage(SwkbdInline* s, void* buffer, u64 size, bool *data_av return rc; } +s32 swkbdInlineGetMaxHeight(SwkbdInline* s) { + bool flag=0; + if (s->calcArg.appearArg.dicFlag || s->wordInfoInitialized || s->dicCustomInitialized) flag = 1; + if (s->calcArg.appearArg.type >= SwkbdType_ZhHans && s->calcArg.appearArg.type <= SwkbdType_Unknown9) flag = 1; + else + flag = flag && !s->calcArg.appearArg.keySetDisableBitmask && (s->calcArg.appearArg.type != SwkbdType_NumPad && s->calcArg.appearArg.type != SwkbdType_QWERTY); + s32 extra_height = flag ? 50 : 0; + s32 height0 = s->calcArg.appearArg.type == SwkbdType_NumPad ? 350 : 400; + height0+= extra_height; + s32 height1 = flag ? 132 : 72; + return s->state == SwkbdState_Unknown6 ? height1 : height0; +} + +s32 swkbdInlineGetTouchRectangles(SwkbdInline* s, SwkbdRect *keytop, SwkbdRect *footer) { + float keytop_max_height = (float)swkbdInlineGetMaxHeight(s); + float footer_max_height = keytop_max_height; + + if (!s->calcArg.footerScalable) { + footer_max_height-= 72.0f; + if (s->calcArg.keytopAsFloating) footer_max_height+= 1.4f; + } + + if (keytop) { + float image_width = 1280.0f; + float width = s->calcArg.keytopScaleX*image_width; + float scale_y = s->calcArg.keytopScaleY; + float tmp_y = (keytop_max_height - 360.0f)*scale_y; + keytop->x = lroundf(((width*-5.0f)+640.0f) + (s->calcArg.keytopTranslateX*image_width)); // This results in a negative value with the default keytopTranslateX. sdknso uses 5.0f, but 0.5f was likely (?) intended - we do the same as sdknso anyway though. + keytop->y = lroundf((360.0f - tmp_y) - (s->calcArg.keytopTranslateY * 720.0f)); + keytop->width = lroundf(width); + keytop->height = lroundf(footer_max_height*scale_y); + } + + if (footer) { + footer->x = 0; + if (s->calcArg.footerScalable) { + footer->y = 0; + footer->width = 0; + footer->height = 0; + } + else { + footer->y = 648; + footer->width = 1280; + footer->height = 72; + } + } + + return s->calcArg.footerScalable ? 1 : 2; +} + +bool swkbdInlineIsUsedTouchPointByKeyboard(SwkbdInline* s, s32 x, s32 y) { + SwkbdRect keytop={0}; + SwkbdRect footer={0}; + + s32 ret = swkbdInlineGetTouchRectangles(s, &keytop, &footer); + + if (keytop.x <= x && keytop.x + keytop.width >= x && keytop.y <= y && keytop.y + keytop.height >= y) + return true; + if (ret >= 2) { + if (footer.x <= x && footer.x + footer.width >= x && footer.y <= y && footer.y + footer.height >= y) + return true; + } + return false; +} + static void _swkbdProcessReply(SwkbdInline* s, SwkbdReplyType ReplyType, size_t size) { size_t stringendoff_utf8 = 0x7D4; size_t stringendoff_utf16 = 0x3EC; @@ -802,6 +867,11 @@ void swkbdInlineAppearEx(SwkbdInline* s, const SwkbdAppearArg* arg, u8 trigger) if (s->version < 0x6000B) trigger=0; // [6.0.0+] s->calcArg.trigger = trigger; s->calcArg.triggerFlag = s->calcArg.trigger!=0; + if (hosversionAtLeast(10,0,0) && (arg->unk_x29 == 1 || arg->unk_x29 == 2)) { + s->calcArg.keytopAsFloating = false; + s->calcArg.footerScalable = true; + s->calcArg.flags |= 0x200; + } _swkbdInlineUpdateAppearFlags(s); s->calcArg.flags = (s->calcArg.flags & ~0x80) | 0x4; } @@ -996,6 +1066,7 @@ void swkbdInlineSetFooterBgAlpha(SwkbdInline* s, float alpha) { } void swkbdInlineSetKeytopAsFloating(SwkbdInline* s, bool flag) { + if (s->state > SwkbdState_Initialized) return; _swkbdInlineSetBoolFlag(s, &s->calcArg.keytopAsFloating, flag, 0x200); } @@ -1015,7 +1086,7 @@ static void _swkbdInlineSetKeytopScale(SwkbdInline* s, float x, float y) { } static void _swkbdInlineSetBalloonScale(SwkbdInline* s, float scale) { - if (s->calcArg.balloonScale == scale) return; + if (s->state > SwkbdState_Initialized || s->calcArg.balloonScale == scale) return; s->calcArg.balloonScale = scale; s->calcArg.flags |= 0x200; } @@ -1034,8 +1105,8 @@ void swkbdInlineSetKeytopTranslate(SwkbdInline* s, float x, float y) { s->calcArg.flags |= 0x200; } -void swkbdInlineSetUSBKeyboardFlag(SwkbdInline* s, bool flag) { - _swkbdInlineSetBoolDisableFlag(s, &s->calcArg.disableUSBKeyboard, flag, 0x800); +void swkbdInlineSetHardwareKeyboardFlag(SwkbdInline* s, bool flag) { + _swkbdInlineSetBoolDisableFlag(s, &s->calcArg.disableHardwareKeyboard, flag, 0x800); } void swkbdInlineSetDirectionalButtonAssignFlag(SwkbdInline* s, bool flag) {