Browse Source

Added virtual keyboard support for Xbox (thanks @ts-13512)

Sam Lantinga 1 year ago
parent
commit
b5d4206b30

+ 1 - 0
VisualC-GDK/SDL/SDL.vcxproj

@@ -839,6 +839,7 @@
     <ClCompile Include="..\..\src\video\windows\SDL_windowsvideo.c" />
     <ClCompile Include="..\..\src\video\windows\SDL_windowsvulkan.c" />
     <ClCompile Include="..\..\src\video\windows\SDL_windowswindow.c" />
+    <ClCompile Include="..\..\src\video\windows\SDL_xboxkeyboard.cpp" />
     <ClCompile Include="..\..\src\video\yuv2rgb\yuv_rgb_lsx.c" />
     <ClCompile Include="..\..\src\video\yuv2rgb\yuv_rgb_sse.c" />
     <ClCompile Include="..\..\src\video\yuv2rgb\yuv_rgb_std.c" />

+ 1 - 0
VisualC-GDK/SDL/SDL.vcxproj.filters

@@ -215,6 +215,7 @@
     <ClCompile Include="..\..\src\video\windows\SDL_windowsvideo.c" />
     <ClCompile Include="..\..\src\video\windows\SDL_windowsvulkan.c" />
     <ClCompile Include="..\..\src\video\windows\SDL_windowswindow.c" />
+    <ClCompile Include="..\..\src\video\windows\SDL_xboxkeyboard.cpp" />
     <ClCompile Include="..\..\src\video\yuv2rgb\yuv_rgb.c" />
     <ClCompile Include="..\..\src\filesystem\windows\SDL_sysfilesystem.c" />
     <ClCompile Include="..\..\src\video\SDL_video_capture.c" />

+ 5 - 0
src/video/windows/SDL_windowskeyboard.c

@@ -210,6 +210,11 @@ void WIN_ResetDeadKeys()
     }
 }
 
+SDL_bool WIN_HasScreenKeyboardSupport(SDL_VideoDevice *_this)
+{
+    return SDL_FALSE;
+}
+
 void WIN_StartTextInput(SDL_VideoDevice *_this)
 {
 #ifndef SDL_DISABLE_WINDOWS_IME

+ 1 - 0
src/video/windows/SDL_windowskeyboard.h

@@ -34,6 +34,7 @@ extern void WIN_StopTextInput(SDL_VideoDevice *_this);
 extern int WIN_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect);
 extern void WIN_ClearComposition(SDL_VideoDevice *_this);
 extern SDL_bool WIN_IsTextInputShown(SDL_VideoDevice *_this);
+extern SDL_bool WIN_HasScreenKeyboardSupport(SDL_VideoDevice *_this);
 
 extern SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, struct SDL_VideoData *videodata);
 

+ 2 - 1
src/video/windows/SDL_windowsvideo.c

@@ -251,9 +251,10 @@ static SDL_VideoDevice *WIN_CreateDevice(void)
     device->Vulkan_CreateSurface = WIN_Vulkan_CreateSurface;
 #endif
 
-#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
     device->StartTextInput = WIN_StartTextInput;
     device->StopTextInput = WIN_StopTextInput;
+    device->HasScreenKeyboardSupport = WIN_HasScreenKeyboardSupport;
+#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
     device->SetTextInputRect = WIN_SetTextInputRect;
     device->ClearComposition = WIN_ClearComposition;
     device->IsTextInputShown = WIN_IsTextInputShown;

+ 109 - 0
src/video/windows/SDL_xboxkeyboard.cpp

@@ -0,0 +1,109 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_WINDOWS && (defined(__XBOXONE__) || defined(__XBOXSERIES__))
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <XAsync.h>
+#include <XGameUI.h>
+#include <XGameRuntime.h>
+
+extern "C" {
+#include "../../events/SDL_keyboard_c.h"
+#include "SDL_windowsvideo.h"
+}
+
+/* Max length passed to XGameUiShowTextEntryAsync */
+#define SDL_XBOX_VIRTUAL_KEYBOARD_MAX_TEXT_LENGTH 1024
+
+
+SDL_bool
+WIN_HasScreenKeyboardSupport(SDL_VideoDevice *_this)
+{
+    return SDL_TRUE;
+}
+
+void
+WIN_StartTextInput(SDL_VideoDevice *_this)
+{
+    XAsyncBlock* asyncBlock = new XAsyncBlock;
+    asyncBlock->context = nullptr;
+    asyncBlock->queue = NULL;
+    asyncBlock->callback = [](XAsyncBlock* async)
+    {
+        async->context;
+        uint32_t textBufSize;
+        HRESULT hr = XGameUiShowTextEntryResultSize(async, &textBufSize);
+
+        if (FAILED(hr))
+        {
+            SDL_Log("XGameUiShowTextEntryResultSize failed: 0x%08X", hr);
+            return;
+        }
+
+        if (textBufSize == 0)
+        {
+            return;
+        }
+
+        char* textBuf = new char[textBufSize + 1];
+        if (textBuf == nullptr)
+        {
+            SDL_Log("Allocating text buffer with size: XGameUiShowTextEntryResultSize(%ul) failed!", textBufSize);
+            return;
+        }
+
+        hr = XGameUiShowTextEntryResult(async, textBufSize, textBuf, nullptr);
+
+        if (FAILED(hr))
+        {
+            SDL_Log("XGameUiShowTextEntryResult failed: 0x%08X", hr);
+            delete[] textBuf;
+            return;
+        }
+
+        SDL_SendKeyboardText(textBuf);
+
+        // Use the text buffer
+       delete[] textBuf;
+    };
+
+    // This can be further improved, title, description, InputScope can be exposed for the user to set.
+    HRESULT hr = XGameUiShowTextEntryAsync(
+        asyncBlock,
+        "Enter text",
+        "",
+        "",
+        XGameUiTextEntryInputScope::Default,
+        SDL_XBOX_VIRTUAL_KEYBOARD_MAX_TEXT_LENGTH
+    );
+}
+
+void
+WIN_StopTextInput(SDL_VideoDevice *_this)
+{
+}
+
+#endif /* SDL_VIDEO_DRIVER_WINDOWS */