2015-06-21 17:33:46 +02:00
|
|
|
/*
|
|
|
|
|
Simple DirectMedia Layer
|
2026-01-01 09:48:19 -08:00
|
|
|
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
|
2015-06-21 17:33:46 +02:00
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
2024-05-16 10:44:37 -04:00
|
|
|
* # CategoryClipboard
|
2015-06-21 17:33:46 +02:00
|
|
|
*
|
2024-05-16 10:44:37 -04:00
|
|
|
* SDL provides access to the system clipboard, both for reading information
|
|
|
|
|
* from other processes and publishing information of its own.
|
|
|
|
|
*
|
|
|
|
|
* This is not just text! SDL apps can access and publish data by mimetype.
|
2024-12-16 01:10:37 -05:00
|
|
|
*
|
|
|
|
|
* ## Basic use (text)
|
|
|
|
|
*
|
2024-12-16 06:13:48 +00:00
|
|
|
* Obtaining and publishing simple text to the system clipboard is as easy as
|
|
|
|
|
* calling SDL_GetClipboardText() and SDL_SetClipboardText(), respectively.
|
|
|
|
|
* These deal with C strings in UTF-8 encoding. Data transmission and encoding
|
|
|
|
|
* conversion is completely managed by SDL.
|
2024-12-16 01:10:37 -05:00
|
|
|
*
|
|
|
|
|
* ## Clipboard callbacks (data other than text)
|
|
|
|
|
*
|
|
|
|
|
* Things get more complicated when the clipboard contains something other
|
2024-12-16 06:13:48 +00:00
|
|
|
* than text. Not only can the system clipboard contain data of any type, in
|
|
|
|
|
* some cases it can contain the same data in different formats! For example,
|
|
|
|
|
* an image painting app might let the user copy a graphic to the clipboard,
|
|
|
|
|
* and offers it in .BMP, .JPG, or .PNG format for other apps to consume.
|
2024-12-16 01:10:37 -05:00
|
|
|
*
|
|
|
|
|
* Obtaining clipboard data ("pasting") like this is a matter of calling
|
|
|
|
|
* SDL_GetClipboardData() and telling it the mimetype of the data you want.
|
|
|
|
|
* But how does one know if that format is available? SDL_HasClipboardData()
|
|
|
|
|
* can report if a specific mimetype is offered, and
|
|
|
|
|
* SDL_GetClipboardMimeTypes() can provide the entire list of mimetypes
|
|
|
|
|
* available, so the app can decide what to do with the data and what formats
|
|
|
|
|
* it can support.
|
|
|
|
|
*
|
|
|
|
|
* Setting the clipboard ("copying") to arbitrary data is done with
|
|
|
|
|
* SDL_SetClipboardData. The app does not provide the data in this call, but
|
|
|
|
|
* rather the mimetypes it is willing to provide and a callback function.
|
|
|
|
|
* During the callback, the app will generate the data. This allows massive
|
|
|
|
|
* data sets to be provided to the clipboard, without any data being copied
|
2024-12-16 06:13:48 +00:00
|
|
|
* before it is explicitly requested. More specifically, it allows an app to
|
|
|
|
|
* offer data in multiple formats without providing a copy of all of them
|
|
|
|
|
* upfront. If the app has an image that it could provide in PNG or JPG
|
2024-12-16 01:10:37 -05:00
|
|
|
* format, it doesn't have to encode it to either of those unless and until
|
|
|
|
|
* something tries to paste it.
|
|
|
|
|
*
|
|
|
|
|
* ## Primary Selection
|
|
|
|
|
*
|
|
|
|
|
* The X11 and Wayland video targets have a concept of the "primary selection"
|
|
|
|
|
* in addition to the usual clipboard. This is generally highlighted (but not
|
|
|
|
|
* explicitly copied) text from various apps. SDL offers APIs for this through
|
2024-12-16 06:13:48 +00:00
|
|
|
* SDL_GetPrimarySelectionText() and SDL_SetPrimarySelectionText(). SDL offers
|
|
|
|
|
* these APIs on platforms without this concept, too, but only so far that it
|
|
|
|
|
* will keep a copy of a string that the app sets for later retrieval; the
|
|
|
|
|
* operating system will not ever attempt to change the string externally if
|
|
|
|
|
* it doesn't support a primary selection.
|
2015-06-21 17:33:46 +02:00
|
|
|
*/
|
|
|
|
|
|
2016-11-20 21:34:54 -08:00
|
|
|
#ifndef SDL_clipboard_h_
|
|
|
|
|
#define SDL_clipboard_h_
|
2015-06-21 17:33:46 +02:00
|
|
|
|
2022-11-26 20:43:38 -08:00
|
|
|
#include <SDL3/SDL_stdinc.h>
|
2024-04-04 18:38:21 +02:00
|
|
|
#include <SDL3/SDL_error.h>
|
2015-06-21 17:33:46 +02:00
|
|
|
|
2022-12-22 11:38:59 -05:00
|
|
|
#include <SDL3/SDL_begin_code.h>
|
2015-06-21 17:33:46 +02:00
|
|
|
/* Set up for C function definitions, even when using C++ */
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
extern "C" {
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Function prototypes */
|
|
|
|
|
|
|
|
|
|
/**
|
2021-03-21 14:18:39 -04:00
|
|
|
* Put UTF-8 text into the clipboard.
|
2015-06-21 17:33:46 +02:00
|
|
|
*
|
2024-06-14 02:09:55 -04:00
|
|
|
* \param text the text to store in the clipboard.
|
2024-09-18 15:33:11 +00:00
|
|
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
|
|
|
|
* information.
|
2021-03-21 14:18:39 -04:00
|
|
|
*
|
2024-12-05 09:45:32 -08:00
|
|
|
* \threadsafety This function should only be called on the main thread.
|
2024-10-24 14:36:06 -04:00
|
|
|
*
|
2025-01-21 13:12:25 -05:00
|
|
|
* \since This function is available since SDL 3.2.0.
|
2021-10-27 01:36:05 +00:00
|
|
|
*
|
2021-03-21 14:18:39 -04:00
|
|
|
* \sa SDL_GetClipboardText
|
|
|
|
|
* \sa SDL_HasClipboardText
|
2015-06-21 17:33:46 +02:00
|
|
|
*/
|
2024-09-18 07:52:28 -07:00
|
|
|
extern SDL_DECLSPEC bool SDLCALL SDL_SetClipboardText(const char *text);
|
2015-06-21 17:33:46 +02:00
|
|
|
|
|
|
|
|
/**
|
2024-07-15 14:00:52 -04:00
|
|
|
* Get UTF-8 text from the clipboard.
|
2021-03-21 14:18:39 -04:00
|
|
|
*
|
2025-07-28 11:43:16 -07:00
|
|
|
* This function returns an empty string if there is not enough memory left
|
2024-10-23 05:42:03 +00:00
|
|
|
* for a copy of the clipboard's content.
|
2021-03-21 14:18:39 -04:00
|
|
|
*
|
2021-09-28 17:03:06 +00:00
|
|
|
* \returns the clipboard text on success or an empty string on failure; call
|
2024-07-27 03:59:43 +00:00
|
|
|
* SDL_GetError() for more information. This should be freed with
|
|
|
|
|
* SDL_free() when it is no longer needed.
|
2015-06-21 17:33:46 +02:00
|
|
|
*
|
2024-12-05 09:45:32 -08:00
|
|
|
* \threadsafety This function should only be called on the main thread.
|
2024-10-24 14:36:06 -04:00
|
|
|
*
|
2025-01-21 13:12:25 -05:00
|
|
|
* \since This function is available since SDL 3.2.0.
|
2021-10-27 01:36:05 +00:00
|
|
|
*
|
2021-03-21 14:18:39 -04:00
|
|
|
* \sa SDL_HasClipboardText
|
|
|
|
|
* \sa SDL_SetClipboardText
|
2015-06-21 17:33:46 +02:00
|
|
|
*/
|
2024-07-28 07:06:22 -07:00
|
|
|
extern SDL_DECLSPEC char * SDLCALL SDL_GetClipboardText(void);
|
2015-06-21 17:33:46 +02:00
|
|
|
|
|
|
|
|
/**
|
2021-03-21 14:18:39 -04:00
|
|
|
* Query whether the clipboard exists and contains a non-empty text string.
|
|
|
|
|
*
|
2024-09-18 07:52:28 -07:00
|
|
|
* \returns true if the clipboard has text, or false if it does not.
|
2021-03-21 14:18:39 -04:00
|
|
|
*
|
2024-12-05 09:45:32 -08:00
|
|
|
* \threadsafety This function should only be called on the main thread.
|
2024-10-24 14:36:06 -04:00
|
|
|
*
|
2025-01-21 13:12:25 -05:00
|
|
|
* \since This function is available since SDL 3.2.0.
|
2015-06-21 17:33:46 +02:00
|
|
|
*
|
2021-03-21 14:18:39 -04:00
|
|
|
* \sa SDL_GetClipboardText
|
|
|
|
|
* \sa SDL_SetClipboardText
|
2015-06-21 17:33:46 +02:00
|
|
|
*/
|
2024-09-18 07:52:28 -07:00
|
|
|
extern SDL_DECLSPEC bool SDLCALL SDL_HasClipboardText(void);
|
2015-06-21 17:33:46 +02:00
|
|
|
|
Add support for X11 primary selection (#6132)
X11 has a so-called primary selection, which you can use by marking text and middle-clicking elsewhere to copy the marked text.
There are 3 new API functions in `SDL_clipboard.h`, which work exactly like their clipboard equivalents.
## Test Instructions
* Run the tests (just a copy of the clipboard tests): `$ ./test/testautomation --filter Clipboard`
* Build and run this small application:
<details>
```C
#include <SDL.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_error(const char *where)
{
const char *errstr = SDL_GetError();
if (errstr == NULL || errstr[0] == '\0')
return;
fprintf(stderr, "SDL Error after '%s': %s\n", where, errstr);
SDL_ClearError();
}
int main()
{
char text_buf[256];
srand(time(NULL));
SDL_Init(SDL_INIT_VIDEO);
print_error("SDL_INIT()");
SDL_Window *window = SDL_CreateWindow("Primary Selection Test", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 400, 400, SDL_WINDOW_SHOWN);
print_error("SDL_CreateWindow()");
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
print_error("SDL_CreateRenderer()");
bool quit = false;
unsigned int do_render = 0;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
print_error("SDL_PollEvent()");
switch (event.type) {
case SDL_QUIT: {
quit = true;
break;
} case SDL_KEYDOWN: {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_q:
quit = true;
break;
case SDLK_c:
snprintf(text_buf, sizeof(text_buf), "foo%d", rand());
SDL_SetClipboardText(text_buf);
print_error("SDL_SetClipboardText()");
printf("clipboard: set_to=\"%s\"\n", text_buf);
break;
case SDLK_v: {
printf("clipboard: has=%d, ", SDL_HasClipboardText());
print_error("SDL_HasClipboardText()");
char *text = SDL_GetClipboardText();
print_error("SDL_GetClipboardText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} case SDLK_d:
snprintf(text_buf, sizeof(text_buf), "bar%d", rand());
SDL_SetPrimarySelectionText(text_buf);
print_error("SDL_SetPrimarySelectionText()");
printf("primselec: set_to=\"%s\"\n", text_buf);
break;
case SDLK_f: {
printf("primselec: has=%d, ", SDL_HasPrimarySelectionText());
print_error("SDL_HasPrimarySelectionText()");
char *text = SDL_GetPrimarySelectionText();
print_error("SDL_GetPrimarySelectionText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} default:
break;
}
break;
} default: {
break;
}}
}
// create less noise with WAYLAND_DEBUG=1
if (do_render == 0) {
SDL_RenderPresent(renderer);
print_error("SDL_RenderPresent()");
}
do_render += 1;
usleep(12000);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
print_error("quit");
return 0;
}
```
</details>
* Use c,v,d,f to get and set the clipboard and primary selection.
* Mark text and middle-click also in other applications.
* For wayland under x:
* `$ mutter --wayland --no-x11 --nested`
* `$ XDG_SESSION_TYPE=wayland SDL_VIDEODRIVER=wayland ./<path_to_test_appl_binary>`
2022-09-14 18:28:35 +02:00
|
|
|
/**
|
|
|
|
|
* Put UTF-8 text into the primary selection.
|
|
|
|
|
*
|
2024-06-14 02:09:55 -04:00
|
|
|
* \param text the text to store in the primary selection.
|
2024-09-18 15:33:11 +00:00
|
|
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
|
|
|
|
* information.
|
Add support for X11 primary selection (#6132)
X11 has a so-called primary selection, which you can use by marking text and middle-clicking elsewhere to copy the marked text.
There are 3 new API functions in `SDL_clipboard.h`, which work exactly like their clipboard equivalents.
## Test Instructions
* Run the tests (just a copy of the clipboard tests): `$ ./test/testautomation --filter Clipboard`
* Build and run this small application:
<details>
```C
#include <SDL.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_error(const char *where)
{
const char *errstr = SDL_GetError();
if (errstr == NULL || errstr[0] == '\0')
return;
fprintf(stderr, "SDL Error after '%s': %s\n", where, errstr);
SDL_ClearError();
}
int main()
{
char text_buf[256];
srand(time(NULL));
SDL_Init(SDL_INIT_VIDEO);
print_error("SDL_INIT()");
SDL_Window *window = SDL_CreateWindow("Primary Selection Test", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 400, 400, SDL_WINDOW_SHOWN);
print_error("SDL_CreateWindow()");
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
print_error("SDL_CreateRenderer()");
bool quit = false;
unsigned int do_render = 0;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
print_error("SDL_PollEvent()");
switch (event.type) {
case SDL_QUIT: {
quit = true;
break;
} case SDL_KEYDOWN: {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_q:
quit = true;
break;
case SDLK_c:
snprintf(text_buf, sizeof(text_buf), "foo%d", rand());
SDL_SetClipboardText(text_buf);
print_error("SDL_SetClipboardText()");
printf("clipboard: set_to=\"%s\"\n", text_buf);
break;
case SDLK_v: {
printf("clipboard: has=%d, ", SDL_HasClipboardText());
print_error("SDL_HasClipboardText()");
char *text = SDL_GetClipboardText();
print_error("SDL_GetClipboardText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} case SDLK_d:
snprintf(text_buf, sizeof(text_buf), "bar%d", rand());
SDL_SetPrimarySelectionText(text_buf);
print_error("SDL_SetPrimarySelectionText()");
printf("primselec: set_to=\"%s\"\n", text_buf);
break;
case SDLK_f: {
printf("primselec: has=%d, ", SDL_HasPrimarySelectionText());
print_error("SDL_HasPrimarySelectionText()");
char *text = SDL_GetPrimarySelectionText();
print_error("SDL_GetPrimarySelectionText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} default:
break;
}
break;
} default: {
break;
}}
}
// create less noise with WAYLAND_DEBUG=1
if (do_render == 0) {
SDL_RenderPresent(renderer);
print_error("SDL_RenderPresent()");
}
do_render += 1;
usleep(12000);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
print_error("quit");
return 0;
}
```
</details>
* Use c,v,d,f to get and set the clipboard and primary selection.
* Mark text and middle-click also in other applications.
* For wayland under x:
* `$ mutter --wayland --no-x11 --nested`
* `$ XDG_SESSION_TYPE=wayland SDL_VIDEODRIVER=wayland ./<path_to_test_appl_binary>`
2022-09-14 18:28:35 +02:00
|
|
|
*
|
2024-12-05 09:45:32 -08:00
|
|
|
* \threadsafety This function should only be called on the main thread.
|
2024-10-24 14:36:06 -04:00
|
|
|
*
|
2025-01-21 13:12:25 -05:00
|
|
|
* \since This function is available since SDL 3.2.0.
|
Add support for X11 primary selection (#6132)
X11 has a so-called primary selection, which you can use by marking text and middle-clicking elsewhere to copy the marked text.
There are 3 new API functions in `SDL_clipboard.h`, which work exactly like their clipboard equivalents.
## Test Instructions
* Run the tests (just a copy of the clipboard tests): `$ ./test/testautomation --filter Clipboard`
* Build and run this small application:
<details>
```C
#include <SDL.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_error(const char *where)
{
const char *errstr = SDL_GetError();
if (errstr == NULL || errstr[0] == '\0')
return;
fprintf(stderr, "SDL Error after '%s': %s\n", where, errstr);
SDL_ClearError();
}
int main()
{
char text_buf[256];
srand(time(NULL));
SDL_Init(SDL_INIT_VIDEO);
print_error("SDL_INIT()");
SDL_Window *window = SDL_CreateWindow("Primary Selection Test", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 400, 400, SDL_WINDOW_SHOWN);
print_error("SDL_CreateWindow()");
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
print_error("SDL_CreateRenderer()");
bool quit = false;
unsigned int do_render = 0;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
print_error("SDL_PollEvent()");
switch (event.type) {
case SDL_QUIT: {
quit = true;
break;
} case SDL_KEYDOWN: {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_q:
quit = true;
break;
case SDLK_c:
snprintf(text_buf, sizeof(text_buf), "foo%d", rand());
SDL_SetClipboardText(text_buf);
print_error("SDL_SetClipboardText()");
printf("clipboard: set_to=\"%s\"\n", text_buf);
break;
case SDLK_v: {
printf("clipboard: has=%d, ", SDL_HasClipboardText());
print_error("SDL_HasClipboardText()");
char *text = SDL_GetClipboardText();
print_error("SDL_GetClipboardText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} case SDLK_d:
snprintf(text_buf, sizeof(text_buf), "bar%d", rand());
SDL_SetPrimarySelectionText(text_buf);
print_error("SDL_SetPrimarySelectionText()");
printf("primselec: set_to=\"%s\"\n", text_buf);
break;
case SDLK_f: {
printf("primselec: has=%d, ", SDL_HasPrimarySelectionText());
print_error("SDL_HasPrimarySelectionText()");
char *text = SDL_GetPrimarySelectionText();
print_error("SDL_GetPrimarySelectionText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} default:
break;
}
break;
} default: {
break;
}}
}
// create less noise with WAYLAND_DEBUG=1
if (do_render == 0) {
SDL_RenderPresent(renderer);
print_error("SDL_RenderPresent()");
}
do_render += 1;
usleep(12000);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
print_error("quit");
return 0;
}
```
</details>
* Use c,v,d,f to get and set the clipboard and primary selection.
* Mark text and middle-click also in other applications.
* For wayland under x:
* `$ mutter --wayland --no-x11 --nested`
* `$ XDG_SESSION_TYPE=wayland SDL_VIDEODRIVER=wayland ./<path_to_test_appl_binary>`
2022-09-14 18:28:35 +02:00
|
|
|
*
|
|
|
|
|
* \sa SDL_GetPrimarySelectionText
|
|
|
|
|
* \sa SDL_HasPrimarySelectionText
|
|
|
|
|
*/
|
2024-09-18 07:52:28 -07:00
|
|
|
extern SDL_DECLSPEC bool SDLCALL SDL_SetPrimarySelectionText(const char *text);
|
Add support for X11 primary selection (#6132)
X11 has a so-called primary selection, which you can use by marking text and middle-clicking elsewhere to copy the marked text.
There are 3 new API functions in `SDL_clipboard.h`, which work exactly like their clipboard equivalents.
## Test Instructions
* Run the tests (just a copy of the clipboard tests): `$ ./test/testautomation --filter Clipboard`
* Build and run this small application:
<details>
```C
#include <SDL.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_error(const char *where)
{
const char *errstr = SDL_GetError();
if (errstr == NULL || errstr[0] == '\0')
return;
fprintf(stderr, "SDL Error after '%s': %s\n", where, errstr);
SDL_ClearError();
}
int main()
{
char text_buf[256];
srand(time(NULL));
SDL_Init(SDL_INIT_VIDEO);
print_error("SDL_INIT()");
SDL_Window *window = SDL_CreateWindow("Primary Selection Test", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 400, 400, SDL_WINDOW_SHOWN);
print_error("SDL_CreateWindow()");
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
print_error("SDL_CreateRenderer()");
bool quit = false;
unsigned int do_render = 0;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
print_error("SDL_PollEvent()");
switch (event.type) {
case SDL_QUIT: {
quit = true;
break;
} case SDL_KEYDOWN: {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_q:
quit = true;
break;
case SDLK_c:
snprintf(text_buf, sizeof(text_buf), "foo%d", rand());
SDL_SetClipboardText(text_buf);
print_error("SDL_SetClipboardText()");
printf("clipboard: set_to=\"%s\"\n", text_buf);
break;
case SDLK_v: {
printf("clipboard: has=%d, ", SDL_HasClipboardText());
print_error("SDL_HasClipboardText()");
char *text = SDL_GetClipboardText();
print_error("SDL_GetClipboardText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} case SDLK_d:
snprintf(text_buf, sizeof(text_buf), "bar%d", rand());
SDL_SetPrimarySelectionText(text_buf);
print_error("SDL_SetPrimarySelectionText()");
printf("primselec: set_to=\"%s\"\n", text_buf);
break;
case SDLK_f: {
printf("primselec: has=%d, ", SDL_HasPrimarySelectionText());
print_error("SDL_HasPrimarySelectionText()");
char *text = SDL_GetPrimarySelectionText();
print_error("SDL_GetPrimarySelectionText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} default:
break;
}
break;
} default: {
break;
}}
}
// create less noise with WAYLAND_DEBUG=1
if (do_render == 0) {
SDL_RenderPresent(renderer);
print_error("SDL_RenderPresent()");
}
do_render += 1;
usleep(12000);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
print_error("quit");
return 0;
}
```
</details>
* Use c,v,d,f to get and set the clipboard and primary selection.
* Mark text and middle-click also in other applications.
* For wayland under x:
* `$ mutter --wayland --no-x11 --nested`
* `$ XDG_SESSION_TYPE=wayland SDL_VIDEODRIVER=wayland ./<path_to_test_appl_binary>`
2022-09-14 18:28:35 +02:00
|
|
|
|
|
|
|
|
/**
|
2024-07-15 14:07:33 -04:00
|
|
|
* Get UTF-8 text from the primary selection.
|
Add support for X11 primary selection (#6132)
X11 has a so-called primary selection, which you can use by marking text and middle-clicking elsewhere to copy the marked text.
There are 3 new API functions in `SDL_clipboard.h`, which work exactly like their clipboard equivalents.
## Test Instructions
* Run the tests (just a copy of the clipboard tests): `$ ./test/testautomation --filter Clipboard`
* Build and run this small application:
<details>
```C
#include <SDL.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_error(const char *where)
{
const char *errstr = SDL_GetError();
if (errstr == NULL || errstr[0] == '\0')
return;
fprintf(stderr, "SDL Error after '%s': %s\n", where, errstr);
SDL_ClearError();
}
int main()
{
char text_buf[256];
srand(time(NULL));
SDL_Init(SDL_INIT_VIDEO);
print_error("SDL_INIT()");
SDL_Window *window = SDL_CreateWindow("Primary Selection Test", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 400, 400, SDL_WINDOW_SHOWN);
print_error("SDL_CreateWindow()");
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
print_error("SDL_CreateRenderer()");
bool quit = false;
unsigned int do_render = 0;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
print_error("SDL_PollEvent()");
switch (event.type) {
case SDL_QUIT: {
quit = true;
break;
} case SDL_KEYDOWN: {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_q:
quit = true;
break;
case SDLK_c:
snprintf(text_buf, sizeof(text_buf), "foo%d", rand());
SDL_SetClipboardText(text_buf);
print_error("SDL_SetClipboardText()");
printf("clipboard: set_to=\"%s\"\n", text_buf);
break;
case SDLK_v: {
printf("clipboard: has=%d, ", SDL_HasClipboardText());
print_error("SDL_HasClipboardText()");
char *text = SDL_GetClipboardText();
print_error("SDL_GetClipboardText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} case SDLK_d:
snprintf(text_buf, sizeof(text_buf), "bar%d", rand());
SDL_SetPrimarySelectionText(text_buf);
print_error("SDL_SetPrimarySelectionText()");
printf("primselec: set_to=\"%s\"\n", text_buf);
break;
case SDLK_f: {
printf("primselec: has=%d, ", SDL_HasPrimarySelectionText());
print_error("SDL_HasPrimarySelectionText()");
char *text = SDL_GetPrimarySelectionText();
print_error("SDL_GetPrimarySelectionText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} default:
break;
}
break;
} default: {
break;
}}
}
// create less noise with WAYLAND_DEBUG=1
if (do_render == 0) {
SDL_RenderPresent(renderer);
print_error("SDL_RenderPresent()");
}
do_render += 1;
usleep(12000);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
print_error("quit");
return 0;
}
```
</details>
* Use c,v,d,f to get and set the clipboard and primary selection.
* Mark text and middle-click also in other applications.
* For wayland under x:
* `$ mutter --wayland --no-x11 --nested`
* `$ XDG_SESSION_TYPE=wayland SDL_VIDEODRIVER=wayland ./<path_to_test_appl_binary>`
2022-09-14 18:28:35 +02:00
|
|
|
*
|
2025-07-28 11:43:16 -07:00
|
|
|
* This function returns an empty string if there is not enough memory left
|
2024-10-23 05:42:03 +00:00
|
|
|
* for a copy of the primary selection's content.
|
Add support for X11 primary selection (#6132)
X11 has a so-called primary selection, which you can use by marking text and middle-clicking elsewhere to copy the marked text.
There are 3 new API functions in `SDL_clipboard.h`, which work exactly like their clipboard equivalents.
## Test Instructions
* Run the tests (just a copy of the clipboard tests): `$ ./test/testautomation --filter Clipboard`
* Build and run this small application:
<details>
```C
#include <SDL.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_error(const char *where)
{
const char *errstr = SDL_GetError();
if (errstr == NULL || errstr[0] == '\0')
return;
fprintf(stderr, "SDL Error after '%s': %s\n", where, errstr);
SDL_ClearError();
}
int main()
{
char text_buf[256];
srand(time(NULL));
SDL_Init(SDL_INIT_VIDEO);
print_error("SDL_INIT()");
SDL_Window *window = SDL_CreateWindow("Primary Selection Test", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 400, 400, SDL_WINDOW_SHOWN);
print_error("SDL_CreateWindow()");
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
print_error("SDL_CreateRenderer()");
bool quit = false;
unsigned int do_render = 0;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
print_error("SDL_PollEvent()");
switch (event.type) {
case SDL_QUIT: {
quit = true;
break;
} case SDL_KEYDOWN: {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_q:
quit = true;
break;
case SDLK_c:
snprintf(text_buf, sizeof(text_buf), "foo%d", rand());
SDL_SetClipboardText(text_buf);
print_error("SDL_SetClipboardText()");
printf("clipboard: set_to=\"%s\"\n", text_buf);
break;
case SDLK_v: {
printf("clipboard: has=%d, ", SDL_HasClipboardText());
print_error("SDL_HasClipboardText()");
char *text = SDL_GetClipboardText();
print_error("SDL_GetClipboardText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} case SDLK_d:
snprintf(text_buf, sizeof(text_buf), "bar%d", rand());
SDL_SetPrimarySelectionText(text_buf);
print_error("SDL_SetPrimarySelectionText()");
printf("primselec: set_to=\"%s\"\n", text_buf);
break;
case SDLK_f: {
printf("primselec: has=%d, ", SDL_HasPrimarySelectionText());
print_error("SDL_HasPrimarySelectionText()");
char *text = SDL_GetPrimarySelectionText();
print_error("SDL_GetPrimarySelectionText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} default:
break;
}
break;
} default: {
break;
}}
}
// create less noise with WAYLAND_DEBUG=1
if (do_render == 0) {
SDL_RenderPresent(renderer);
print_error("SDL_RenderPresent()");
}
do_render += 1;
usleep(12000);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
print_error("quit");
return 0;
}
```
</details>
* Use c,v,d,f to get and set the clipboard and primary selection.
* Mark text and middle-click also in other applications.
* For wayland under x:
* `$ mutter --wayland --no-x11 --nested`
* `$ XDG_SESSION_TYPE=wayland SDL_VIDEODRIVER=wayland ./<path_to_test_appl_binary>`
2022-09-14 18:28:35 +02:00
|
|
|
*
|
2022-09-14 16:29:16 +00:00
|
|
|
* \returns the primary selection text on success or an empty string on
|
2024-07-27 03:59:43 +00:00
|
|
|
* failure; call SDL_GetError() for more information. This should be
|
|
|
|
|
* freed with SDL_free() when it is no longer needed.
|
Add support for X11 primary selection (#6132)
X11 has a so-called primary selection, which you can use by marking text and middle-clicking elsewhere to copy the marked text.
There are 3 new API functions in `SDL_clipboard.h`, which work exactly like their clipboard equivalents.
## Test Instructions
* Run the tests (just a copy of the clipboard tests): `$ ./test/testautomation --filter Clipboard`
* Build and run this small application:
<details>
```C
#include <SDL.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_error(const char *where)
{
const char *errstr = SDL_GetError();
if (errstr == NULL || errstr[0] == '\0')
return;
fprintf(stderr, "SDL Error after '%s': %s\n", where, errstr);
SDL_ClearError();
}
int main()
{
char text_buf[256];
srand(time(NULL));
SDL_Init(SDL_INIT_VIDEO);
print_error("SDL_INIT()");
SDL_Window *window = SDL_CreateWindow("Primary Selection Test", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 400, 400, SDL_WINDOW_SHOWN);
print_error("SDL_CreateWindow()");
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
print_error("SDL_CreateRenderer()");
bool quit = false;
unsigned int do_render = 0;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
print_error("SDL_PollEvent()");
switch (event.type) {
case SDL_QUIT: {
quit = true;
break;
} case SDL_KEYDOWN: {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_q:
quit = true;
break;
case SDLK_c:
snprintf(text_buf, sizeof(text_buf), "foo%d", rand());
SDL_SetClipboardText(text_buf);
print_error("SDL_SetClipboardText()");
printf("clipboard: set_to=\"%s\"\n", text_buf);
break;
case SDLK_v: {
printf("clipboard: has=%d, ", SDL_HasClipboardText());
print_error("SDL_HasClipboardText()");
char *text = SDL_GetClipboardText();
print_error("SDL_GetClipboardText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} case SDLK_d:
snprintf(text_buf, sizeof(text_buf), "bar%d", rand());
SDL_SetPrimarySelectionText(text_buf);
print_error("SDL_SetPrimarySelectionText()");
printf("primselec: set_to=\"%s\"\n", text_buf);
break;
case SDLK_f: {
printf("primselec: has=%d, ", SDL_HasPrimarySelectionText());
print_error("SDL_HasPrimarySelectionText()");
char *text = SDL_GetPrimarySelectionText();
print_error("SDL_GetPrimarySelectionText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} default:
break;
}
break;
} default: {
break;
}}
}
// create less noise with WAYLAND_DEBUG=1
if (do_render == 0) {
SDL_RenderPresent(renderer);
print_error("SDL_RenderPresent()");
}
do_render += 1;
usleep(12000);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
print_error("quit");
return 0;
}
```
</details>
* Use c,v,d,f to get and set the clipboard and primary selection.
* Mark text and middle-click also in other applications.
* For wayland under x:
* `$ mutter --wayland --no-x11 --nested`
* `$ XDG_SESSION_TYPE=wayland SDL_VIDEODRIVER=wayland ./<path_to_test_appl_binary>`
2022-09-14 18:28:35 +02:00
|
|
|
*
|
2024-12-05 09:45:32 -08:00
|
|
|
* \threadsafety This function should only be called on the main thread.
|
2024-10-24 14:36:06 -04:00
|
|
|
*
|
2025-01-21 13:12:25 -05:00
|
|
|
* \since This function is available since SDL 3.2.0.
|
Add support for X11 primary selection (#6132)
X11 has a so-called primary selection, which you can use by marking text and middle-clicking elsewhere to copy the marked text.
There are 3 new API functions in `SDL_clipboard.h`, which work exactly like their clipboard equivalents.
## Test Instructions
* Run the tests (just a copy of the clipboard tests): `$ ./test/testautomation --filter Clipboard`
* Build and run this small application:
<details>
```C
#include <SDL.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_error(const char *where)
{
const char *errstr = SDL_GetError();
if (errstr == NULL || errstr[0] == '\0')
return;
fprintf(stderr, "SDL Error after '%s': %s\n", where, errstr);
SDL_ClearError();
}
int main()
{
char text_buf[256];
srand(time(NULL));
SDL_Init(SDL_INIT_VIDEO);
print_error("SDL_INIT()");
SDL_Window *window = SDL_CreateWindow("Primary Selection Test", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 400, 400, SDL_WINDOW_SHOWN);
print_error("SDL_CreateWindow()");
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
print_error("SDL_CreateRenderer()");
bool quit = false;
unsigned int do_render = 0;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
print_error("SDL_PollEvent()");
switch (event.type) {
case SDL_QUIT: {
quit = true;
break;
} case SDL_KEYDOWN: {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_q:
quit = true;
break;
case SDLK_c:
snprintf(text_buf, sizeof(text_buf), "foo%d", rand());
SDL_SetClipboardText(text_buf);
print_error("SDL_SetClipboardText()");
printf("clipboard: set_to=\"%s\"\n", text_buf);
break;
case SDLK_v: {
printf("clipboard: has=%d, ", SDL_HasClipboardText());
print_error("SDL_HasClipboardText()");
char *text = SDL_GetClipboardText();
print_error("SDL_GetClipboardText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} case SDLK_d:
snprintf(text_buf, sizeof(text_buf), "bar%d", rand());
SDL_SetPrimarySelectionText(text_buf);
print_error("SDL_SetPrimarySelectionText()");
printf("primselec: set_to=\"%s\"\n", text_buf);
break;
case SDLK_f: {
printf("primselec: has=%d, ", SDL_HasPrimarySelectionText());
print_error("SDL_HasPrimarySelectionText()");
char *text = SDL_GetPrimarySelectionText();
print_error("SDL_GetPrimarySelectionText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} default:
break;
}
break;
} default: {
break;
}}
}
// create less noise with WAYLAND_DEBUG=1
if (do_render == 0) {
SDL_RenderPresent(renderer);
print_error("SDL_RenderPresent()");
}
do_render += 1;
usleep(12000);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
print_error("quit");
return 0;
}
```
</details>
* Use c,v,d,f to get and set the clipboard and primary selection.
* Mark text and middle-click also in other applications.
* For wayland under x:
* `$ mutter --wayland --no-x11 --nested`
* `$ XDG_SESSION_TYPE=wayland SDL_VIDEODRIVER=wayland ./<path_to_test_appl_binary>`
2022-09-14 18:28:35 +02:00
|
|
|
*
|
|
|
|
|
* \sa SDL_HasPrimarySelectionText
|
|
|
|
|
* \sa SDL_SetPrimarySelectionText
|
|
|
|
|
*/
|
2024-07-28 07:06:22 -07:00
|
|
|
extern SDL_DECLSPEC char * SDLCALL SDL_GetPrimarySelectionText(void);
|
Add support for X11 primary selection (#6132)
X11 has a so-called primary selection, which you can use by marking text and middle-clicking elsewhere to copy the marked text.
There are 3 new API functions in `SDL_clipboard.h`, which work exactly like their clipboard equivalents.
## Test Instructions
* Run the tests (just a copy of the clipboard tests): `$ ./test/testautomation --filter Clipboard`
* Build and run this small application:
<details>
```C
#include <SDL.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_error(const char *where)
{
const char *errstr = SDL_GetError();
if (errstr == NULL || errstr[0] == '\0')
return;
fprintf(stderr, "SDL Error after '%s': %s\n", where, errstr);
SDL_ClearError();
}
int main()
{
char text_buf[256];
srand(time(NULL));
SDL_Init(SDL_INIT_VIDEO);
print_error("SDL_INIT()");
SDL_Window *window = SDL_CreateWindow("Primary Selection Test", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 400, 400, SDL_WINDOW_SHOWN);
print_error("SDL_CreateWindow()");
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
print_error("SDL_CreateRenderer()");
bool quit = false;
unsigned int do_render = 0;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
print_error("SDL_PollEvent()");
switch (event.type) {
case SDL_QUIT: {
quit = true;
break;
} case SDL_KEYDOWN: {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_q:
quit = true;
break;
case SDLK_c:
snprintf(text_buf, sizeof(text_buf), "foo%d", rand());
SDL_SetClipboardText(text_buf);
print_error("SDL_SetClipboardText()");
printf("clipboard: set_to=\"%s\"\n", text_buf);
break;
case SDLK_v: {
printf("clipboard: has=%d, ", SDL_HasClipboardText());
print_error("SDL_HasClipboardText()");
char *text = SDL_GetClipboardText();
print_error("SDL_GetClipboardText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} case SDLK_d:
snprintf(text_buf, sizeof(text_buf), "bar%d", rand());
SDL_SetPrimarySelectionText(text_buf);
print_error("SDL_SetPrimarySelectionText()");
printf("primselec: set_to=\"%s\"\n", text_buf);
break;
case SDLK_f: {
printf("primselec: has=%d, ", SDL_HasPrimarySelectionText());
print_error("SDL_HasPrimarySelectionText()");
char *text = SDL_GetPrimarySelectionText();
print_error("SDL_GetPrimarySelectionText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} default:
break;
}
break;
} default: {
break;
}}
}
// create less noise with WAYLAND_DEBUG=1
if (do_render == 0) {
SDL_RenderPresent(renderer);
print_error("SDL_RenderPresent()");
}
do_render += 1;
usleep(12000);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
print_error("quit");
return 0;
}
```
</details>
* Use c,v,d,f to get and set the clipboard and primary selection.
* Mark text and middle-click also in other applications.
* For wayland under x:
* `$ mutter --wayland --no-x11 --nested`
* `$ XDG_SESSION_TYPE=wayland SDL_VIDEODRIVER=wayland ./<path_to_test_appl_binary>`
2022-09-14 18:28:35 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Query whether the primary selection exists and contains a non-empty text
|
|
|
|
|
* string.
|
|
|
|
|
*
|
2024-09-18 15:33:11 +00:00
|
|
|
* \returns true if the primary selection has text, or false if it does not.
|
Add support for X11 primary selection (#6132)
X11 has a so-called primary selection, which you can use by marking text and middle-clicking elsewhere to copy the marked text.
There are 3 new API functions in `SDL_clipboard.h`, which work exactly like their clipboard equivalents.
## Test Instructions
* Run the tests (just a copy of the clipboard tests): `$ ./test/testautomation --filter Clipboard`
* Build and run this small application:
<details>
```C
#include <SDL.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_error(const char *where)
{
const char *errstr = SDL_GetError();
if (errstr == NULL || errstr[0] == '\0')
return;
fprintf(stderr, "SDL Error after '%s': %s\n", where, errstr);
SDL_ClearError();
}
int main()
{
char text_buf[256];
srand(time(NULL));
SDL_Init(SDL_INIT_VIDEO);
print_error("SDL_INIT()");
SDL_Window *window = SDL_CreateWindow("Primary Selection Test", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 400, 400, SDL_WINDOW_SHOWN);
print_error("SDL_CreateWindow()");
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
print_error("SDL_CreateRenderer()");
bool quit = false;
unsigned int do_render = 0;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
print_error("SDL_PollEvent()");
switch (event.type) {
case SDL_QUIT: {
quit = true;
break;
} case SDL_KEYDOWN: {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_q:
quit = true;
break;
case SDLK_c:
snprintf(text_buf, sizeof(text_buf), "foo%d", rand());
SDL_SetClipboardText(text_buf);
print_error("SDL_SetClipboardText()");
printf("clipboard: set_to=\"%s\"\n", text_buf);
break;
case SDLK_v: {
printf("clipboard: has=%d, ", SDL_HasClipboardText());
print_error("SDL_HasClipboardText()");
char *text = SDL_GetClipboardText();
print_error("SDL_GetClipboardText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} case SDLK_d:
snprintf(text_buf, sizeof(text_buf), "bar%d", rand());
SDL_SetPrimarySelectionText(text_buf);
print_error("SDL_SetPrimarySelectionText()");
printf("primselec: set_to=\"%s\"\n", text_buf);
break;
case SDLK_f: {
printf("primselec: has=%d, ", SDL_HasPrimarySelectionText());
print_error("SDL_HasPrimarySelectionText()");
char *text = SDL_GetPrimarySelectionText();
print_error("SDL_GetPrimarySelectionText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} default:
break;
}
break;
} default: {
break;
}}
}
// create less noise with WAYLAND_DEBUG=1
if (do_render == 0) {
SDL_RenderPresent(renderer);
print_error("SDL_RenderPresent()");
}
do_render += 1;
usleep(12000);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
print_error("quit");
return 0;
}
```
</details>
* Use c,v,d,f to get and set the clipboard and primary selection.
* Mark text and middle-click also in other applications.
* For wayland under x:
* `$ mutter --wayland --no-x11 --nested`
* `$ XDG_SESSION_TYPE=wayland SDL_VIDEODRIVER=wayland ./<path_to_test_appl_binary>`
2022-09-14 18:28:35 +02:00
|
|
|
*
|
2024-12-05 09:45:32 -08:00
|
|
|
* \threadsafety This function should only be called on the main thread.
|
2024-10-24 14:36:06 -04:00
|
|
|
*
|
2025-01-21 13:12:25 -05:00
|
|
|
* \since This function is available since SDL 3.2.0.
|
Add support for X11 primary selection (#6132)
X11 has a so-called primary selection, which you can use by marking text and middle-clicking elsewhere to copy the marked text.
There are 3 new API functions in `SDL_clipboard.h`, which work exactly like their clipboard equivalents.
## Test Instructions
* Run the tests (just a copy of the clipboard tests): `$ ./test/testautomation --filter Clipboard`
* Build and run this small application:
<details>
```C
#include <SDL.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_error(const char *where)
{
const char *errstr = SDL_GetError();
if (errstr == NULL || errstr[0] == '\0')
return;
fprintf(stderr, "SDL Error after '%s': %s\n", where, errstr);
SDL_ClearError();
}
int main()
{
char text_buf[256];
srand(time(NULL));
SDL_Init(SDL_INIT_VIDEO);
print_error("SDL_INIT()");
SDL_Window *window = SDL_CreateWindow("Primary Selection Test", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 400, 400, SDL_WINDOW_SHOWN);
print_error("SDL_CreateWindow()");
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
print_error("SDL_CreateRenderer()");
bool quit = false;
unsigned int do_render = 0;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
print_error("SDL_PollEvent()");
switch (event.type) {
case SDL_QUIT: {
quit = true;
break;
} case SDL_KEYDOWN: {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_q:
quit = true;
break;
case SDLK_c:
snprintf(text_buf, sizeof(text_buf), "foo%d", rand());
SDL_SetClipboardText(text_buf);
print_error("SDL_SetClipboardText()");
printf("clipboard: set_to=\"%s\"\n", text_buf);
break;
case SDLK_v: {
printf("clipboard: has=%d, ", SDL_HasClipboardText());
print_error("SDL_HasClipboardText()");
char *text = SDL_GetClipboardText();
print_error("SDL_GetClipboardText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} case SDLK_d:
snprintf(text_buf, sizeof(text_buf), "bar%d", rand());
SDL_SetPrimarySelectionText(text_buf);
print_error("SDL_SetPrimarySelectionText()");
printf("primselec: set_to=\"%s\"\n", text_buf);
break;
case SDLK_f: {
printf("primselec: has=%d, ", SDL_HasPrimarySelectionText());
print_error("SDL_HasPrimarySelectionText()");
char *text = SDL_GetPrimarySelectionText();
print_error("SDL_GetPrimarySelectionText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} default:
break;
}
break;
} default: {
break;
}}
}
// create less noise with WAYLAND_DEBUG=1
if (do_render == 0) {
SDL_RenderPresent(renderer);
print_error("SDL_RenderPresent()");
}
do_render += 1;
usleep(12000);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
print_error("quit");
return 0;
}
```
</details>
* Use c,v,d,f to get and set the clipboard and primary selection.
* Mark text and middle-click also in other applications.
* For wayland under x:
* `$ mutter --wayland --no-x11 --nested`
* `$ XDG_SESSION_TYPE=wayland SDL_VIDEODRIVER=wayland ./<path_to_test_appl_binary>`
2022-09-14 18:28:35 +02:00
|
|
|
*
|
|
|
|
|
* \sa SDL_GetPrimarySelectionText
|
|
|
|
|
* \sa SDL_SetPrimarySelectionText
|
|
|
|
|
*/
|
2024-09-18 07:52:28 -07:00
|
|
|
extern SDL_DECLSPEC bool SDLCALL SDL_HasPrimarySelectionText(void);
|
Add support for X11 primary selection (#6132)
X11 has a so-called primary selection, which you can use by marking text and middle-clicking elsewhere to copy the marked text.
There are 3 new API functions in `SDL_clipboard.h`, which work exactly like their clipboard equivalents.
## Test Instructions
* Run the tests (just a copy of the clipboard tests): `$ ./test/testautomation --filter Clipboard`
* Build and run this small application:
<details>
```C
#include <SDL.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_error(const char *where)
{
const char *errstr = SDL_GetError();
if (errstr == NULL || errstr[0] == '\0')
return;
fprintf(stderr, "SDL Error after '%s': %s\n", where, errstr);
SDL_ClearError();
}
int main()
{
char text_buf[256];
srand(time(NULL));
SDL_Init(SDL_INIT_VIDEO);
print_error("SDL_INIT()");
SDL_Window *window = SDL_CreateWindow("Primary Selection Test", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 400, 400, SDL_WINDOW_SHOWN);
print_error("SDL_CreateWindow()");
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
print_error("SDL_CreateRenderer()");
bool quit = false;
unsigned int do_render = 0;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
print_error("SDL_PollEvent()");
switch (event.type) {
case SDL_QUIT: {
quit = true;
break;
} case SDL_KEYDOWN: {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
case SDLK_q:
quit = true;
break;
case SDLK_c:
snprintf(text_buf, sizeof(text_buf), "foo%d", rand());
SDL_SetClipboardText(text_buf);
print_error("SDL_SetClipboardText()");
printf("clipboard: set_to=\"%s\"\n", text_buf);
break;
case SDLK_v: {
printf("clipboard: has=%d, ", SDL_HasClipboardText());
print_error("SDL_HasClipboardText()");
char *text = SDL_GetClipboardText();
print_error("SDL_GetClipboardText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} case SDLK_d:
snprintf(text_buf, sizeof(text_buf), "bar%d", rand());
SDL_SetPrimarySelectionText(text_buf);
print_error("SDL_SetPrimarySelectionText()");
printf("primselec: set_to=\"%s\"\n", text_buf);
break;
case SDLK_f: {
printf("primselec: has=%d, ", SDL_HasPrimarySelectionText());
print_error("SDL_HasPrimarySelectionText()");
char *text = SDL_GetPrimarySelectionText();
print_error("SDL_GetPrimarySelectionText()");
printf("text=\"%s\"\n", text);
SDL_free(text);
break;
} default:
break;
}
break;
} default: {
break;
}}
}
// create less noise with WAYLAND_DEBUG=1
if (do_render == 0) {
SDL_RenderPresent(renderer);
print_error("SDL_RenderPresent()");
}
do_render += 1;
usleep(12000);
}
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
print_error("quit");
return 0;
}
```
</details>
* Use c,v,d,f to get and set the clipboard and primary selection.
* Mark text and middle-click also in other applications.
* For wayland under x:
* `$ mutter --wayland --no-x11 --nested`
* `$ XDG_SESSION_TYPE=wayland SDL_VIDEODRIVER=wayland ./<path_to_test_appl_binary>`
2022-09-14 18:28:35 +02:00
|
|
|
|
2023-04-21 20:07:24 +02:00
|
|
|
/**
|
|
|
|
|
* Callback function that will be called when data for the specified mime-type
|
|
|
|
|
* is requested by the OS.
|
|
|
|
|
*
|
2024-04-11 12:59:41 +00:00
|
|
|
* The callback function is called with NULL as the mime_type when the
|
|
|
|
|
* clipboard is cleared or new data is set. The clipboard is automatically
|
|
|
|
|
* cleared in SDL_Quit().
|
2023-07-03 23:24:01 -07:00
|
|
|
*
|
2025-07-28 11:43:16 -07:00
|
|
|
* \param userdata a pointer to the provided user data.
|
2024-06-14 02:09:55 -04:00
|
|
|
* \param mime_type the requested mime-type.
|
|
|
|
|
* \param size a pointer filled in with the length of the returned data.
|
2024-04-11 12:59:41 +00:00
|
|
|
* \returns a pointer to the data for the provided mime-type. Returning NULL
|
2025-10-09 19:21:44 +00:00
|
|
|
* or setting the length to 0 will cause zero length data to be sent
|
|
|
|
|
* to the "receiver", which should be able to handle this. The
|
|
|
|
|
* returned data will not be freed, so it needs to be retained and
|
|
|
|
|
* dealt with internally.
|
2023-04-21 20:07:24 +02:00
|
|
|
*
|
2025-01-21 13:12:25 -05:00
|
|
|
* \since This function is available since SDL 3.2.0.
|
2023-04-21 20:07:24 +02:00
|
|
|
*
|
|
|
|
|
* \sa SDL_SetClipboardData
|
|
|
|
|
*/
|
2023-07-03 23:24:01 -07:00
|
|
|
typedef const void *(SDLCALL *SDL_ClipboardDataCallback)(void *userdata, const char *mime_type, size_t *size);
|
|
|
|
|
|
|
|
|
|
/**
|
2025-07-28 18:58:19 +00:00
|
|
|
* Callback function that will be called when the clipboard is cleared, or
|
|
|
|
|
* when new data is set.
|
2023-07-03 23:24:01 -07:00
|
|
|
*
|
2025-07-28 11:43:16 -07:00
|
|
|
* \param userdata a pointer to the provided user data.
|
2023-07-03 23:24:01 -07:00
|
|
|
*
|
2025-01-21 13:12:25 -05:00
|
|
|
* \since This function is available since SDL 3.2.0.
|
2023-07-03 23:24:01 -07:00
|
|
|
*
|
|
|
|
|
* \sa SDL_SetClipboardData
|
|
|
|
|
*/
|
|
|
|
|
typedef void (SDLCALL *SDL_ClipboardCleanupCallback)(void *userdata);
|
2023-04-21 20:07:24 +02:00
|
|
|
|
|
|
|
|
/**
|
2024-04-08 22:36:57 -04:00
|
|
|
* Offer clipboard data to the OS.
|
2023-04-21 20:07:24 +02:00
|
|
|
*
|
|
|
|
|
* Tell the operating system that the application is offering clipboard data
|
2024-12-16 01:10:37 -05:00
|
|
|
* for each of the provided mime-types. Once another application requests the
|
|
|
|
|
* data the callback function will be called, allowing it to generate and
|
2023-04-21 20:07:24 +02:00
|
|
|
* respond with the data for the requested mime-type.
|
|
|
|
|
*
|
2023-07-06 03:08:15 +00:00
|
|
|
* The size of text data does not include any terminator, and the text does
|
2025-07-28 11:43:16 -07:00
|
|
|
* not need to be null-terminated (e.g., you can directly copy a portion of a
|
2024-12-16 01:10:37 -05:00
|
|
|
* document).
|
2023-07-04 21:17:53 -07:00
|
|
|
*
|
2024-06-14 02:09:55 -04:00
|
|
|
* \param callback a function pointer to the function that provides the
|
|
|
|
|
* clipboard data.
|
|
|
|
|
* \param cleanup a function pointer to the function that cleans up the
|
|
|
|
|
* clipboard data.
|
|
|
|
|
* \param userdata an opaque pointer that will be forwarded to the callbacks.
|
2025-07-28 18:58:19 +00:00
|
|
|
* \param mime_types a list of mime-types that are being offered. SDL copies
|
|
|
|
|
* the given list.
|
2024-06-14 02:09:55 -04:00
|
|
|
* \param num_mime_types the number of mime-types in the mime_types list.
|
2024-09-18 15:33:11 +00:00
|
|
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
|
|
|
|
* information.
|
2023-04-21 20:07:24 +02:00
|
|
|
*
|
2024-12-05 09:45:32 -08:00
|
|
|
* \threadsafety This function should only be called on the main thread.
|
2024-10-24 14:36:06 -04:00
|
|
|
*
|
2025-01-21 13:12:25 -05:00
|
|
|
* \since This function is available since SDL 3.2.0.
|
2023-04-21 20:07:24 +02:00
|
|
|
*
|
2024-03-17 11:00:15 -07:00
|
|
|
* \sa SDL_ClearClipboardData
|
2023-04-21 20:07:24 +02:00
|
|
|
* \sa SDL_GetClipboardData
|
|
|
|
|
* \sa SDL_HasClipboardData
|
|
|
|
|
*/
|
2025-01-01 07:54:55 -08:00
|
|
|
extern SDL_DECLSPEC bool SDLCALL SDL_SetClipboardData(SDL_ClipboardDataCallback callback, SDL_ClipboardCleanupCallback cleanup, void *userdata, const char **mime_types, size_t num_mime_types);
|
2023-04-21 20:07:24 +02:00
|
|
|
|
|
|
|
|
/**
|
2024-04-08 22:36:57 -04:00
|
|
|
* Clear the clipboard data.
|
2023-05-12 14:55:13 +00:00
|
|
|
*
|
2024-09-18 15:33:11 +00:00
|
|
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
|
|
|
|
* information.
|
2023-07-07 10:24:14 +02:00
|
|
|
*
|
2024-12-05 09:45:32 -08:00
|
|
|
* \threadsafety This function should only be called on the main thread.
|
2024-10-24 14:36:06 -04:00
|
|
|
*
|
2025-01-21 13:12:25 -05:00
|
|
|
* \since This function is available since SDL 3.2.0.
|
2023-07-03 23:24:01 -07:00
|
|
|
*
|
|
|
|
|
* \sa SDL_SetClipboardData
|
2023-04-21 20:07:24 +02:00
|
|
|
*/
|
2024-09-18 07:52:28 -07:00
|
|
|
extern SDL_DECLSPEC bool SDLCALL SDL_ClearClipboardData(void);
|
2023-04-21 20:07:24 +02:00
|
|
|
|
|
|
|
|
/**
|
2025-07-28 11:43:16 -07:00
|
|
|
* Get the data from the clipboard for a given mime type.
|
2023-04-21 20:07:24 +02:00
|
|
|
*
|
2023-07-06 03:08:15 +00:00
|
|
|
* The size of text data does not include the terminator, but the text is
|
2025-07-28 11:43:16 -07:00
|
|
|
* guaranteed to be null-terminated.
|
2023-07-04 21:17:53 -07:00
|
|
|
*
|
2024-06-14 02:09:55 -04:00
|
|
|
* \param mime_type the mime type to read from the clipboard.
|
|
|
|
|
* \param size a pointer filled in with the length of the returned data.
|
2023-05-12 14:55:13 +00:00
|
|
|
* \returns the retrieved data buffer or NULL on failure; call SDL_GetError()
|
2024-07-27 03:59:43 +00:00
|
|
|
* for more information. This should be freed with SDL_free() when it
|
|
|
|
|
* is no longer needed.
|
2024-07-19 11:08:03 -07:00
|
|
|
*
|
2024-12-05 09:45:32 -08:00
|
|
|
* \threadsafety This function should only be called on the main thread.
|
2024-10-24 14:36:06 -04:00
|
|
|
*
|
2025-01-21 13:12:25 -05:00
|
|
|
* \since This function is available since SDL 3.2.0.
|
2023-04-21 20:07:24 +02:00
|
|
|
*
|
2024-04-15 16:56:12 +00:00
|
|
|
* \sa SDL_HasClipboardData
|
2023-04-21 20:07:24 +02:00
|
|
|
* \sa SDL_SetClipboardData
|
|
|
|
|
*/
|
2024-07-28 07:06:22 -07:00
|
|
|
extern SDL_DECLSPEC void * SDLCALL SDL_GetClipboardData(const char *mime_type, size_t *size);
|
2023-04-21 20:07:24 +02:00
|
|
|
|
|
|
|
|
/**
|
2024-04-08 22:36:57 -04:00
|
|
|
* Query whether there is data in the clipboard for the provided mime type.
|
2023-04-21 20:07:24 +02:00
|
|
|
*
|
2025-07-28 11:43:16 -07:00
|
|
|
* \param mime_type the mime type to check for data.
|
|
|
|
|
* \returns true if data exists in the clipboard for the provided mime type,
|
2024-09-18 15:33:11 +00:00
|
|
|
* false if it does not.
|
2023-04-21 20:07:24 +02:00
|
|
|
*
|
2024-12-05 09:45:32 -08:00
|
|
|
* \threadsafety This function should only be called on the main thread.
|
2024-10-24 14:36:06 -04:00
|
|
|
*
|
2025-01-21 13:12:25 -05:00
|
|
|
* \since This function is available since SDL 3.2.0.
|
2023-04-21 20:07:24 +02:00
|
|
|
*
|
|
|
|
|
* \sa SDL_SetClipboardData
|
|
|
|
|
* \sa SDL_GetClipboardData
|
|
|
|
|
*/
|
2024-09-18 07:52:28 -07:00
|
|
|
extern SDL_DECLSPEC bool SDLCALL SDL_HasClipboardData(const char *mime_type);
|
2015-06-21 17:33:46 +02:00
|
|
|
|
2024-09-27 14:10:46 -07:00
|
|
|
/**
|
|
|
|
|
* Retrieve the list of mime types available in the clipboard.
|
|
|
|
|
*
|
|
|
|
|
* \param num_mime_types a pointer filled with the number of mime types, may
|
|
|
|
|
* be NULL.
|
2025-07-28 11:43:16 -07:00
|
|
|
* \returns a null-terminated array of strings with mime types, or NULL on
|
2024-09-27 14:10:46 -07:00
|
|
|
* failure; call SDL_GetError() for more information. This should be
|
|
|
|
|
* freed with SDL_free() when it is no longer needed.
|
|
|
|
|
*
|
2024-12-05 09:45:32 -08:00
|
|
|
* \threadsafety This function should only be called on the main thread.
|
2024-10-24 14:36:06 -04:00
|
|
|
*
|
2025-01-21 13:12:25 -05:00
|
|
|
* \since This function is available since SDL 3.2.0.
|
2024-09-27 14:10:46 -07:00
|
|
|
*
|
|
|
|
|
* \sa SDL_SetClipboardData
|
|
|
|
|
*/
|
|
|
|
|
extern SDL_DECLSPEC char ** SDLCALL SDL_GetClipboardMimeTypes(size_t *num_mime_types);
|
|
|
|
|
|
2015-06-21 17:33:46 +02:00
|
|
|
/* Ends C function definitions when using C++ */
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2022-12-22 11:38:59 -05:00
|
|
|
#include <SDL3/SDL_close_code.h>
|
2015-06-21 17:33:46 +02:00
|
|
|
|
2016-11-20 21:34:54 -08:00
|
|
|
#endif /* SDL_clipboard_h_ */
|