Fixed clipboard (text copy & paste) implementation (#380)

- fixed "SDL_GetClipboardText" memory leak
- forcing unicode clipboard data format on Windows (UTF-16LE system, UTF-8 in-game)
- all "get_clipboard_text" functions return a zero-width string in case of failure, instead of NULL
This commit is contained in:
Radek Krzyśków 2024-10-22 14:24:13 +02:00 committed by GitHub
parent 85a81d3d81
commit b4b66c369a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 47 additions and 20 deletions

View file

@ -113,7 +113,7 @@ static void gfx_dummy_wm_start_text_input(void) {
static void gfx_dummy_wm_stop_text_input(void) {
}
static void gfx_dummy_wm_set_clipboard_text(UNUSED char* text) {
static void gfx_dummy_wm_set_clipboard_text(UNUSED const char* text) {
}
static void gfx_dummy_wm_set_cursor_visible(UNUSED bool visible) {

View file

@ -719,26 +719,40 @@ void gfx_dxgi_start_text_input(void) { inTextInput = TRUE; }
void gfx_dxgi_stop_text_input(void) { inTextInput = FALSE; }
static char* gfx_dxgi_get_clipboard_text(void) {
static char clipboard_buf[WAPI_CLIPBOARD_BUFSIZ];
clipboard_buf[0] = '\0';
if (OpenClipboard(NULL)) {
HANDLE clip = GetClipboardData(CF_TEXT);
CloseClipboard();
return (char*)clip;
LPCWSTR text = (LPCWSTR)GetClipboardData(CF_UNICODETEXT);
if (text != NULL) {
WideCharToMultiByte(CP_UTF8, 0, text, (-1), clipboard_buf, WAPI_CLIPBOARD_BUFSIZ, NULL, NULL);
}
return NULL;
CloseClipboard();
}
clipboard_buf[WAPI_CLIPBOARD_BUFSIZ - 1] = '\0';
return clipboard_buf;
}
void gfx_dxgi_set_clipboard_text(char* text) {
if (OpenClipboard(NULL)) {
HGLOBAL clipbuffer;
char *buffer;
void gfx_dxgi_set_clipboard_text(const char* text) {
if (!OpenClipboard(NULL)) { return; }
EmptyClipboard();
clipbuffer = GlobalAlloc(GMEM_DDESHARE, strlen(text) + 1);
buffer = (char *) GlobalLock(clipbuffer);
strcpy(buffer, LPCSTR(text));
GlobalUnlock(clipbuffer);
SetClipboardData(CF_TEXT, clipbuffer);
CloseClipboard();
int cch = MultiByteToWideChar(CP_UTF8, 0, text, (-1), NULL, 0);
if (cch > 0) {
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, cch * sizeof(WCHAR));
if (hMem != NULL) {
LPWSTR wcsBuffer = (LPWSTR)GlobalLock(hMem);
if (wcsBuffer != NULL) {
MultiByteToWideChar(CP_UTF8, 0, text, (-1), wcsBuffer, cch);
GlobalUnlock(hMem);
SetClipboardData(CF_UNICODETEXT, hMem);
} else {
GlobalFree(hMem);
}
}
}
CloseClipboard();
}
void gfx_dxgi_set_cursor_visible(bool visible) { ShowCursor(visible); }

View file

@ -211,8 +211,8 @@ static bool gfx_sdl_has_focus(void) {
static void gfx_sdl_start_text_input(void) { return; }
static void gfx_sdl_stop_text_input(void) { return; }
static char* gfx_sdl_get_clipboard_text(void) { return NULL; }
static void gfx_sdl_set_clipboard_text(char* text) { return; }
static char* gfx_sdl_get_clipboard_text(void) { return ""; }
static void gfx_sdl_set_clipboard_text(UNUSED const char* text) { return; }
static void gfx_sdl_set_cursor_visible(bool visible) { SDL_ShowCursor(visible ? SDL_ENABLE : SDL_DISABLE); }
struct GfxWindowManagerAPI gfx_sdl = {

View file

@ -304,8 +304,19 @@ static bool gfx_sdl_has_focus(void) {
static void gfx_sdl_start_text_input(void) { SDL_StartTextInput(); }
static void gfx_sdl_stop_text_input(void) { SDL_StopTextInput(); }
static char* gfx_sdl_get_clipboard_text(void) { return SDL_GetClipboardText(); }
static void gfx_sdl_set_clipboard_text(char* text) { SDL_SetClipboardText(text); }
static char* gfx_sdl_get_clipboard_text(void) {
static char clipboard_buf[WAPI_CLIPBOARD_BUFSIZ];
char* text = SDL_GetClipboardText();
strncpy(clipboard_buf, text, WAPI_CLIPBOARD_BUFSIZ - 1);
SDL_free(text);
clipboard_buf[WAPI_CLIPBOARD_BUFSIZ - 1] = '\0';
return clipboard_buf;
}
static void gfx_sdl_set_clipboard_text(const char* text) { SDL_SetClipboardText(text); }
static void gfx_sdl_set_cursor_visible(bool visible) { SDL_ShowCursor(visible ? SDL_ENABLE : SDL_DISABLE); }
struct GfxWindowManagerAPI gfx_sdl = {

View file

@ -7,6 +7,8 @@
// special value for window position that signifies centered position
#define WAPI_WIN_CENTERPOS 0xFFFFFFFF
#define WAPI_CLIPBOARD_BUFSIZ 1024
typedef bool (*kb_callback_t)(int code);
struct GfxWindowManagerAPI {
@ -23,7 +25,7 @@ struct GfxWindowManagerAPI {
void (*start_text_input)(void);
void (*stop_text_input)(void);
char* (*get_clipboard_text)(void);
void (*set_clipboard_text)(char*);
void (*set_clipboard_text)(const char*);
void (*set_cursor_visible)(bool);
void (*delay)(unsigned int ms);
int (*get_max_msaa)(void);