diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj
index 53926d49a1..872aff1626 100644
--- a/VisualC-GDK/SDL/SDL.vcxproj
+++ b/VisualC-GDK/SDL/SDL.vcxproj
@@ -839,6 +839,7 @@
+
diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters
index 39aac2b531..1e07dc754e 100644
--- a/VisualC-GDK/SDL/SDL.vcxproj.filters
+++ b/VisualC-GDK/SDL/SDL.vcxproj.filters
@@ -215,6 +215,7 @@
+
diff --git a/src/video/windows/SDL_windowskeyboard.c b/src/video/windows/SDL_windowskeyboard.c
index 46104649e8..7b7fa97711 100644
--- a/src/video/windows/SDL_windowskeyboard.c
+++ b/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
diff --git a/src/video/windows/SDL_windowskeyboard.h b/src/video/windows/SDL_windowskeyboard.h
index 76f8233e30..7756f7181e 100644
--- a/src/video/windows/SDL_windowskeyboard.h
+++ b/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);
diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c
index 7100159830..b6152d3629 100644
--- a/src/video/windows/SDL_windowsvideo.c
+++ b/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;
diff --git a/src/video/windows/SDL_xboxkeyboard.cpp b/src/video/windows/SDL_xboxkeyboard.cpp
new file mode 100644
index 0000000000..342a7cdfa2
--- /dev/null
+++ b/src/video/windows/SDL_xboxkeyboard.cpp
@@ -0,0 +1,109 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2024 Sam Lantinga
+
+ 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
+#include
+#include
+#include
+
+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 */