Atlas - testclipboard.c
Home / ext / SDL / test Lines: 1 | Size: 7931 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Copyright (C) 1997-2026 Sam Lantinga <[email protected]> 3 4 This software is provided 'as-is', without any express or implied 5 warranty. In no event will the authors be held liable for any damages 6 arising from the use of this software. 7 8 Permission is granted to anyone to use this software for any purpose, 9 including commercial applications, and to alter it and redistribute it 10 freely. 11*/ 12 13#define SDL_MAIN_USE_CALLBACKS 1 14#include <SDL3/SDL.h> 15#include <SDL3/SDL_main.h> 16 17#include "icon.h" 18 19static SDL_Window *window = NULL; 20static SDL_Renderer *renderer = NULL; 21 22static const char *mime_types[] = { 23 "text/plain", 24 "image/png", 25}; 26 27static const char *supported_image_mime_types[] = { 28 "image/bmp", 29 "image/png", 30}; 31 32static const void *ClipboardDataCallback(void *userdata, const char *mime_type, size_t *size) 33{ 34 if (SDL_strcmp(mime_type, "text/plain") == 0) { 35 const char *text = "Hello world!"; 36 *size = SDL_strlen(text); 37 return text; 38 } else if (SDL_strcmp(mime_type, "image/png") == 0) { 39 *size = icon_png_len; 40 return icon_png; 41 } else { 42 SDL_Log("Called with unexpected mime type: %s", mime_type); 43 return NULL; 44 } 45} 46 47SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) 48{ 49 if (!SDL_Init(SDL_INIT_VIDEO)) { 50 SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); 51 return SDL_APP_FAILURE; 52 } 53 54 if (!SDL_CreateWindowAndRenderer("testclipboard", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) { 55 SDL_Log("Couldn't create window and renderer: %s", SDL_GetError()); 56 return SDL_APP_FAILURE; 57 } 58 return SDL_APP_CONTINUE; 59} 60 61 62SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) 63{ 64 switch (event->type) { 65 case SDL_EVENT_KEY_DOWN: 66 if (event->key.key == SDLK_ESCAPE) { 67 return SDL_APP_SUCCESS; 68 } 69 if (event->key.key == SDLK_C) { 70 if (event->key.mod & SDL_KMOD_CTRL) { 71 SDL_SetClipboardData(ClipboardDataCallback, NULL, NULL, mime_types, SDL_arraysize(mime_types)); 72 } else if (event->key.mod & SDL_KMOD_ALT) { 73 SDL_ClearClipboardData(); 74 } 75 } else if (event->key.key == SDLK_P) { 76 if (event->key.mod & SDL_KMOD_CTRL) { 77 SDL_SetPrimarySelectionText("SDL Primary Selection Text!"); 78 } else if (event->key.mod & SDL_KMOD_ALT) { 79 SDL_SetPrimarySelectionText(NULL); 80 } 81 } 82 break; 83 84 case SDL_EVENT_CLIPBOARD_UPDATE: 85 if (event->clipboard.num_mime_types > 0) { 86 SDL_Log("Clipboard updated:"); 87 for (int i = 0; event->clipboard.mime_types[i]; ++i) { 88 SDL_Log(" %s", event->clipboard.mime_types[i]); 89 } 90 } else { 91 SDL_Log("Clipboard cleared"); 92 } 93 break; 94 95 case SDL_EVENT_QUIT: 96 return SDL_APP_SUCCESS; 97 98 default: 99 break; 100 } 101 102 return SDL_APP_CONTINUE; 103} 104 105static float PrintClipboardText(float x, float y, const char *mime_type) 106{ 107 size_t size; 108 void *data = SDL_GetClipboardData(mime_type, &size); 109 if (data) { 110 char *text = (char *)data; 111 if (size > 2 && text[2] == '\0') { 112 /* UCS-4 data */ 113 text = (char *)SDL_iconv_string("UTF-8", "UCS-4", data, size+4); 114 } else if (size > 1 && text[1] == '\0') { 115 /* UCS-2 data */ 116 text = (char *)SDL_iconv_string("UTF-8", "UCS-2", data, size+2); 117 } 118 if (text) { 119 SDL_RenderDebugText(renderer, x, y, text); 120 } 121 if (text != data) { 122 SDL_free(text); 123 } 124 SDL_free(data); 125 return SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE + 2.0f; 126 } 127 return 0.0f; 128} 129 130static float PrintPrimarySelectionText(float x, float y) 131{ 132 if (SDL_HasPrimarySelectionText()) { 133 SDL_RenderDebugText(renderer, x, y, SDL_GetPrimarySelectionText()); 134 return SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE + 2.0f; 135 } 136 return 0.0f; 137} 138 139static bool IsImageMIMETypeSupported(const char *mime_type) 140{ 141 for (int i = 0; i < SDL_arraysize(supported_image_mime_types); ++i) { 142 if (SDL_strcmp(mime_type, supported_image_mime_types[i]) == 0) { 143 return true; 144 } 145 } 146 147 return false; 148} 149 150static float PrintClipboardImage(float x, float y, const char *mime_type) 151{ 152 float h = 0.0f; 153 154 /* We don't actually need to read this data each frame, but this is a simple example */ 155 if (IsImageMIMETypeSupported(mime_type)) { 156 size_t size; 157 void *data = SDL_GetClipboardData(mime_type, &size); 158 if (data) { 159 float w = 0.0f; 160 bool rendered = false; 161 SDL_IOStream *stream = SDL_IOFromConstMem(data, size); 162 if (stream) { 163 SDL_Surface *surface = SDL_LoadSurface_IO(stream, false); 164 if (surface) { 165 SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface); 166 if (texture) { 167 SDL_GetTextureSize(texture, &w, &h); 168 169 SDL_FRect dst = { x, y, w, h }; 170 rendered = SDL_RenderTexture(renderer, texture, NULL, &dst); 171 SDL_DestroyTexture(texture); 172 } 173 SDL_DestroySurface(surface); 174 } 175 SDL_CloseIO(stream); 176 } 177 if (!rendered) { 178 SDL_RenderDebugText(renderer, x, y, SDL_GetError()); 179 h += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE + 2.0f; 180 } 181 SDL_free(data); 182 } else { 183 SDL_RenderDebugText(renderer, x, y, "No data returned"); 184 h += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE + 2.0f; 185 } 186 } else { 187 SDL_RenderDebugText(renderer, x, y, "Unsupported MIME type"); 188 h += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE + 2.0f; 189 } 190 191 return h + 2.0f; 192} 193 194static float PrintClipboardContents(float x, float y) 195{ 196 char **clipboard_mime_types = SDL_GetClipboardMimeTypes(NULL); 197 if (clipboard_mime_types) { 198 for (int i = 0; clipboard_mime_types[i]; ++i) { 199 const char *mime_type = clipboard_mime_types[i]; 200 SDL_RenderDebugText(renderer, x, y, mime_type); 201 y += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE + 2; 202 if (SDL_strncmp(mime_type, "text/", 5) == 0) { 203 y += PrintClipboardText(x + SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * 2, y, mime_type); 204 } else if (SDL_strncmp(mime_type, "image/", 6) == 0) { 205 y += PrintClipboardImage(x + SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * 2, y, mime_type); 206 } 207 } 208 SDL_free(clipboard_mime_types); 209 } 210 211 return y + 2.0f; 212} 213 214SDL_AppResult SDL_AppIterate(void *appstate) 215{ 216 SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); 217 SDL_RenderClear(renderer); 218 219 SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); 220 float x = 4.0f; 221 float y = 4.0f; 222 SDL_RenderDebugText(renderer, x, y, "Press Ctrl+C to copy content to the clipboard (Alt+C to clear)"); 223 y += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * 2; 224 SDL_RenderDebugText(renderer, x, y, "Press Ctrl+P to set the primary selection text (Alt+P to clear)"); 225 y += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * 2; 226 SDL_RenderDebugText(renderer, x, y, "Clipboard contents:"); 227 x += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * 2; 228 y += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE + 2; 229 y = PrintClipboardContents(x, y); 230 if (SDL_HasPrimarySelectionText()) { 231 x = 4.0f; 232 SDL_RenderDebugText(renderer, x, y, "Primary selection text contents:"); 233 y += SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE + 2; 234 PrintPrimarySelectionText(x + SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * 2, y); 235 } 236 237 SDL_RenderPresent(renderer); 238 239 return SDL_APP_CONTINUE; 240} 241 242void SDL_AppQuit(void *appstate, SDL_AppResult result) 243{ 244} 245 246[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.