Clipboard data API revamp
The clipboard data API is now supported on all platforms, at least for internal use.main
parent
61ff86617a
commit
35876da3c4
|
@ -511,6 +511,7 @@
|
|||
<ClInclude Include="..\..\src\video\SDL_blit_auto.h" />
|
||||
<ClInclude Include="..\..\src\video\SDL_blit_copy.h" />
|
||||
<ClInclude Include="..\..\src\video\SDL_blit_slow.h" />
|
||||
<ClInclude Include="..\..\src\video\SDL_clipboard_c.h" />
|
||||
<ClInclude Include="..\..\src\video\SDL_egl_c.h" />
|
||||
<ClInclude Include="..\..\src\video\SDL_pixels_c.h" />
|
||||
<ClInclude Include="..\..\src\video\SDL_rect_c.h" />
|
||||
|
@ -785,4 +786,4 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -573,6 +573,9 @@
|
|||
<ClInclude Include="..\..\src\video\SDL_blit_slow.h">
|
||||
<Filter>video</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\video\SDL_clipboard_c.h">
|
||||
<Filter>video</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\video\SDL_pixels_c.h">
|
||||
<Filter>video</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1386,4 +1389,4 @@
|
|||
<ItemGroup>
|
||||
<ResourceCompile Include="..\..\src\core\windows\version.rc" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -169,6 +169,7 @@
|
|||
<ClInclude Include="..\src\video\SDL_blit_auto.h" />
|
||||
<ClInclude Include="..\src\video\SDL_blit_copy.h" />
|
||||
<ClInclude Include="..\src\video\SDL_blit_slow.h" />
|
||||
<ClInclude Include="..\src\video\SDL_clipboard_c.h" />
|
||||
<ClInclude Include="..\src\video\SDL_egl_c.h" />
|
||||
<ClInclude Include="..\src\video\SDL_pixels_c.h" />
|
||||
<ClInclude Include="..\src\video\SDL_rect_c.h" />
|
||||
|
|
|
@ -366,6 +366,9 @@
|
|||
<ClInclude Include="..\src\video\SDL_blit_slow.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\video\SDL_clipboard_c.h">
|
||||
<Filter>video</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\video\SDL_egl_c.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -433,6 +433,7 @@
|
|||
<ClInclude Include="..\..\src\video\SDL_blit_auto.h" />
|
||||
<ClInclude Include="..\..\src\video\SDL_blit_copy.h" />
|
||||
<ClInclude Include="..\..\src\video\SDL_blit_slow.h" />
|
||||
<ClInclude Include="..\..\src\video\SDL_clipboard_c.h" />
|
||||
<ClInclude Include="..\..\src\video\SDL_egl_c.h" />
|
||||
<ClInclude Include="..\..\src\video\SDL_pixels_c.h" />
|
||||
<ClInclude Include="..\..\src\video\SDL_rect_c.h" />
|
||||
|
|
|
@ -564,6 +564,9 @@
|
|||
<ClInclude Include="..\..\src\video\SDL_blit_slow.h">
|
||||
<Filter>video</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\video\SDL_clipboard_c.h">
|
||||
<Filter>video</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\video\SDL_pixels_c.h">
|
||||
<Filter>video</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -133,9 +133,12 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasPrimarySelectionText(void);
|
|||
* Callback function that will be called when data for the specified mime-type
|
||||
* is requested by the OS.
|
||||
*
|
||||
* \param size The length of the returned data
|
||||
* \param mime_type The requested mime-type
|
||||
* 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().
|
||||
*
|
||||
* \param userdata A pointer to provided user data
|
||||
* \param mime_type The requested mime-type
|
||||
* \param size A pointer filled in with the length of the returned data
|
||||
* \returns a pointer to the data for the provided mime-type. Returning NULL or
|
||||
* setting length to 0 will cause no data to be sent to the "receiver". It is
|
||||
* up to the receiver to handle this. Essentially returning no data is more or
|
||||
|
@ -147,7 +150,18 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasPrimarySelectionText(void);
|
|||
*
|
||||
* \sa SDL_SetClipboardData
|
||||
*/
|
||||
typedef void *(SDLCALL *SDL_ClipboardDataCallback)(size_t *size, const char *mime_type, void *userdata);
|
||||
typedef const void *(SDLCALL *SDL_ClipboardDataCallback)(void *userdata, const char *mime_type, size_t *size);
|
||||
|
||||
/**
|
||||
* Callback function that will be called when the clipboard is cleared, or new data is set.
|
||||
*
|
||||
* \param userdata A pointer to provided user data
|
||||
*
|
||||
* \since This function is available since SDL 3.0.0.
|
||||
*
|
||||
* \sa SDL_SetClipboardData
|
||||
*/
|
||||
typedef void (SDLCALL *SDL_ClipboardCleanupCallback)(void *userdata);
|
||||
|
||||
/**
|
||||
* Offer clipboard data to the OS
|
||||
|
@ -157,46 +171,39 @@ typedef void *(SDLCALL *SDL_ClipboardDataCallback)(size_t *size, const char *mim
|
|||
* data the callback function will be called allowing it to generate and
|
||||
* respond with the data for the requested mime-type.
|
||||
*
|
||||
* The userdata submitted to this function needs to be freed manually. The
|
||||
* following scenarios need to be handled:
|
||||
*
|
||||
* - When the programs clipboard is replaced (cancelled)
|
||||
* SDL_EVENT_CLIPBOARD_CANCELLED
|
||||
* - Before calling SDL_Quit()
|
||||
*
|
||||
* \param callback A function pointer to the function that provides the
|
||||
* clipboard data
|
||||
* \param mime_count The number of mime-types in the mime_types list
|
||||
* \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
|
||||
* \param mime_types A list of mime-types that are being offered
|
||||
* \param userdata An opaque pointer that will be forwarded to the callback
|
||||
* \param num_mime_types The number of mime-types in the mime_types list
|
||||
* \returns 0 on success or a negative error code on failure; call
|
||||
* SDL_GetError() for more information.
|
||||
*
|
||||
* \since This function is available since SDL 3.0.0.
|
||||
*
|
||||
* \sa SDL_ClipboardDataCallback
|
||||
* \sa SDL_GetClipboardUserdata
|
||||
* \sa SDL_SetClipboardData
|
||||
* \sa SDL_GetClipboardData
|
||||
* \sa SDL_HasClipboardData
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_SetClipboardData(SDL_ClipboardDataCallback callback, size_t mime_count,
|
||||
const char **mime_types, void *userdata);
|
||||
extern DECLSPEC int SDLCALL SDL_SetClipboardData(SDL_ClipboardDataCallback callback, SDL_ClipboardCleanupCallback cleanup, void *userdata, const char **mime_types, size_t num_mime_types);
|
||||
|
||||
/**
|
||||
* Retrieve previously set userdata if any.
|
||||
*
|
||||
* \returns a pointer to the data or NULL if no data exists
|
||||
* Clear the clipboard data
|
||||
*
|
||||
* \since This function is available since SDL 3.0.0.
|
||||
*
|
||||
* \sa SDL_SetClipboardData
|
||||
*/
|
||||
extern DECLSPEC void *SDLCALL SDL_GetClipboardUserdata(void);
|
||||
extern DECLSPEC int SDLCALL SDL_ClearClipboardData();
|
||||
|
||||
/**
|
||||
* Get the data from clipboard for a given mime type
|
||||
*
|
||||
* \param length Length of the data
|
||||
* \param mime_type The mime type to read from the clipboard
|
||||
* \param size A pointer filled in with the length of the returned data
|
||||
* \returns the retrieved data buffer or NULL on failure; call SDL_GetError()
|
||||
* for more information. Caller must call SDL_free() on the returned
|
||||
* pointer when done with it.
|
||||
|
@ -205,7 +212,7 @@ extern DECLSPEC void *SDLCALL SDL_GetClipboardUserdata(void);
|
|||
*
|
||||
* \sa SDL_SetClipboardData
|
||||
*/
|
||||
extern DECLSPEC void *SDLCALL SDL_GetClipboardData(size_t *length, const char *mime_type);
|
||||
extern DECLSPEC void *SDLCALL SDL_GetClipboardData(const char *mime_type, size_t *size);
|
||||
|
||||
/**
|
||||
* Query whether there is data in the clipboard for the provided mime type
|
||||
|
|
|
@ -540,9 +540,9 @@ typedef struct SDL_DropEvent
|
|||
*
|
||||
* \sa SDL_SetClipboardData
|
||||
*/
|
||||
typedef struct SDL_ClipboardCancelled
|
||||
typedef struct SDL_ClipboardEvent
|
||||
{
|
||||
Uint32 type; /**< ::SDL_EVENT_CLIPBOARD_CANCELLED or ::SDL_EVENT_CLIPBOARD_UPDATE */
|
||||
Uint32 type; /**< ::SDL_EVENT_CLIPBOARD_UPDATE or ::SDL_EVENT_CLIPBOARD_CANCELLED */
|
||||
Uint64 timestamp; /**< In nanoseconds, populated using SDL_GetTicksNS() */
|
||||
void *userdata; /**< User data if any has been set. NULL for ::SDL_EVENT_CLIPBOARD_UPDATE */
|
||||
} SDL_ClipboardEvent;
|
||||
|
|
|
@ -162,7 +162,6 @@ SDL3_0.0.0 {
|
|||
SDL_GetCPUCount;
|
||||
SDL_GetClipboardData;
|
||||
SDL_GetClipboardText;
|
||||
SDL_GetClipboardUserdata;
|
||||
SDL_GetClosestFullscreenDisplayMode;
|
||||
SDL_GetCurrentAudioDriver;
|
||||
SDL_GetCurrentDisplayMode;
|
||||
|
@ -869,6 +868,7 @@ SDL3_0.0.0 {
|
|||
SDL_wcsncmp;
|
||||
SDL_wcsstr;
|
||||
SDL_wcstol;
|
||||
SDL_ClearClipboardData;
|
||||
# extra symbols go here (don't modify this line)
|
||||
local: *;
|
||||
};
|
||||
|
|
|
@ -186,7 +186,6 @@
|
|||
#define SDL_GetCPUCount SDL_GetCPUCount_REAL
|
||||
#define SDL_GetClipboardData SDL_GetClipboardData_REAL
|
||||
#define SDL_GetClipboardText SDL_GetClipboardText_REAL
|
||||
#define SDL_GetClipboardUserdata SDL_GetClipboardUserdata_REAL
|
||||
#define SDL_GetClosestFullscreenDisplayMode SDL_GetClosestFullscreenDisplayMode_REAL
|
||||
#define SDL_GetCurrentAudioDriver SDL_GetCurrentAudioDriver_REAL
|
||||
#define SDL_GetCurrentDisplayMode SDL_GetCurrentDisplayMode_REAL
|
||||
|
@ -895,3 +894,4 @@
|
|||
#define SDL_wcstol SDL_wcstol_REAL
|
||||
|
||||
/* New API symbols are added at the end */
|
||||
#define SDL_ClearClipboardData SDL_ClearClipboardData_REAL
|
||||
|
|
|
@ -259,9 +259,8 @@ SDL_DYNAPI_PROC(int,SDL_GetAudioStreamFormat,(SDL_AudioStream *a, SDL_AudioForma
|
|||
SDL_DYNAPI_PROC(char*,SDL_GetBasePath,(void),(),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_GetCPUCacheLineSize,(void),(),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_GetCPUCount,(void),(),return)
|
||||
SDL_DYNAPI_PROC(void*,SDL_GetClipboardData,(size_t *a, const char *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(void*,SDL_GetClipboardData,(const char *a, size_t *b),(a,b),return)
|
||||
SDL_DYNAPI_PROC(char*,SDL_GetClipboardText,(void),(),return)
|
||||
SDL_DYNAPI_PROC(void*,SDL_GetClipboardUserdata,(void),(),return)
|
||||
SDL_DYNAPI_PROC(const SDL_DisplayMode*,SDL_GetClosestFullscreenDisplayMode,(SDL_DisplayID a, int b, int c, float d, SDL_bool e),(a,b,c,d,e),return)
|
||||
SDL_DYNAPI_PROC(const char*,SDL_GetCurrentAudioDriver,(void),(),return)
|
||||
SDL_DYNAPI_PROC(const SDL_DisplayMode*,SDL_GetCurrentDisplayMode,(SDL_DisplayID a),(a),return)
|
||||
|
@ -666,7 +665,7 @@ SDL_DYNAPI_PROC(int,SDL_SendGamepadEffect,(SDL_Gamepad *a, const void *b, int c)
|
|||
SDL_DYNAPI_PROC(int,SDL_SendJoystickEffect,(SDL_Joystick *a, const void *b, int c),(a,b,c),return)
|
||||
SDL_DYNAPI_PROC(void,SDL_SetAssertionHandler,(SDL_AssertionHandler a, void *b),(a,b),)
|
||||
SDL_DYNAPI_PROC(int,SDL_SetAudioStreamFormat,(SDL_AudioStream *a, SDL_AudioFormat b, int c, int d, SDL_AudioFormat e, int f, int g),(a,b,c,d,e,f,g),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_SetClipboardData,(SDL_ClipboardDataCallback a, size_t b, const char **c, void *d),(a,b,c,d),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_SetClipboardData,(SDL_ClipboardDataCallback a, SDL_ClipboardCleanupCallback b, void *c, const char **d, size_t e),(a,b,c,d,e),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_SetClipboardText,(const char *a),(a),return)
|
||||
SDL_DYNAPI_PROC(int,SDL_SetCursor,(SDL_Cursor *a),(a),return)
|
||||
SDL_DYNAPI_PROC(void,SDL_SetEventEnabled,(Uint32 a, SDL_bool b),(a,b),)
|
||||
|
@ -940,3 +939,4 @@ SDL_DYNAPI_PROC(wchar_t*,SDL_wcsstr,(const wchar_t *a, const wchar_t *b),(a,b),r
|
|||
SDL_DYNAPI_PROC(long,SDL_wcstol,(const wchar_t *a, wchar_t **b, int c),(a,b,c),return)
|
||||
|
||||
/* New API symbols are added at the end */
|
||||
SDL_DYNAPI_PROC(int,SDL_ClearClipboardData,(void),(),return)
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#define SDL_clipboardevents_c_h_
|
||||
|
||||
extern int SDL_SendClipboardUpdate(void);
|
||||
|
||||
extern int SDL_SendClipboardCancelled(void *userdata);
|
||||
|
||||
#endif /* SDL_clipboardevents_c_h_ */
|
||||
|
|
|
@ -210,6 +210,8 @@ static void SDL_LogEvent(const SDL_Event *event)
|
|||
break;
|
||||
SDL_EVENT_CASE(SDL_EVENT_CLIPBOARD_UPDATE)
|
||||
break;
|
||||
SDL_EVENT_CASE(SDL_EVENT_CLIPBOARD_CANCELLED)
|
||||
break;
|
||||
SDL_EVENT_CASE(SDL_EVENT_RENDER_TARGETS_RESET)
|
||||
break;
|
||||
SDL_EVENT_CASE(SDL_EVENT_RENDER_DEVICE_RESET)
|
||||
|
|
|
@ -1757,6 +1757,9 @@ static void SDLTest_PrintEvent(SDL_Event *event)
|
|||
case SDL_EVENT_CLIPBOARD_UPDATE:
|
||||
SDL_Log("SDL EVENT: Clipboard updated");
|
||||
break;
|
||||
case SDL_EVENT_CLIPBOARD_CANCELLED:
|
||||
SDL_Log("SDL EVENT: Clipboard ownership canceled");
|
||||
break;
|
||||
|
||||
case SDL_EVENT_FINGER_MOTION:
|
||||
SDL_Log("SDL EVENT: Finger: motion touch=%ld, finger=%ld, x=%f, y=%f, dx=%f, dy=%f, pressure=%f",
|
||||
|
@ -1824,10 +1827,69 @@ static void SDLTest_PrintEvent(SDL_Event *event)
|
|||
}
|
||||
}
|
||||
|
||||
static void SDLTest_ScreenShot(SDL_Renderer *renderer)
|
||||
#define SCREENSHOT_FILE "screenshot.bmp"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *image;
|
||||
size_t size;
|
||||
} SDLTest_ClipboardData;
|
||||
|
||||
static void SDLTest_ScreenShotClipboardCleanup(void *context)
|
||||
{
|
||||
SDLTest_ClipboardData *data = (SDLTest_ClipboardData *)context;
|
||||
|
||||
SDL_Log("Cleaning up screenshot image data\n");
|
||||
|
||||
if (data->image) {
|
||||
SDL_free(data->image);
|
||||
}
|
||||
SDL_free(data);
|
||||
}
|
||||
|
||||
static const void *SDLTest_ScreenShotClipboardProvider(void *context, const char *mime_type, size_t *size)
|
||||
{
|
||||
SDLTest_ClipboardData *data = (SDLTest_ClipboardData *)context;
|
||||
|
||||
SDL_Log("Providing screenshot image data to clipboard!\n");
|
||||
|
||||
if (!data->image) {
|
||||
SDL_RWops *file;
|
||||
|
||||
file = SDL_RWFromFile(SCREENSHOT_FILE, "r");
|
||||
if (file) {
|
||||
size_t length = (size_t)SDL_RWsize(file);
|
||||
void *image = SDL_malloc(length);
|
||||
if (image) {
|
||||
if (SDL_RWread(file, image, length) != length) {
|
||||
SDL_Log("Couldn't read %s: %s\n", SCREENSHOT_FILE, SDL_GetError());
|
||||
SDL_free(image);
|
||||
image = NULL;
|
||||
}
|
||||
}
|
||||
SDL_RWclose(file);
|
||||
|
||||
if (image) {
|
||||
data->image = image;
|
||||
data->size = length;
|
||||
}
|
||||
} else {
|
||||
SDL_Log("Couldn't load %s: %s\n", SCREENSHOT_FILE, SDL_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
*size = data->size;
|
||||
return data->image;
|
||||
}
|
||||
|
||||
static void SDLTest_CopyScreenShot(SDL_Renderer *renderer)
|
||||
{
|
||||
SDL_Rect viewport;
|
||||
SDL_Surface *surface;
|
||||
const char *image_formats[] = {
|
||||
"image/bmp"
|
||||
};
|
||||
SDLTest_ClipboardData *clipboard_data;
|
||||
|
||||
if (renderer == NULL) {
|
||||
return;
|
||||
|
@ -1849,11 +1911,50 @@ static void SDLTest_ScreenShot(SDL_Renderer *renderer)
|
|||
return;
|
||||
}
|
||||
|
||||
if (SDL_SaveBMP(surface, "screenshot.bmp") < 0) {
|
||||
SDL_Log("Couldn't save screenshot.bmp: %s\n", SDL_GetError());
|
||||
if (SDL_SaveBMP(surface, SCREENSHOT_FILE) < 0) {
|
||||
SDL_Log("Couldn't save %s: %s\n", SCREENSHOT_FILE, SDL_GetError());
|
||||
SDL_free(surface);
|
||||
return;
|
||||
}
|
||||
SDL_free(surface);
|
||||
|
||||
clipboard_data = (SDLTest_ClipboardData *)SDL_calloc(1, sizeof(*clipboard_data));
|
||||
if (!clipboard_data) {
|
||||
SDL_Log("Couldn't allocate clipboard data\n");
|
||||
return;
|
||||
}
|
||||
SDL_SetClipboardData(SDLTest_ScreenShotClipboardProvider, SDLTest_ScreenShotClipboardCleanup, clipboard_data, image_formats, SDL_arraysize(image_formats));
|
||||
SDL_Log("Saved screenshot to %s and clipboard\n", SCREENSHOT_FILE);
|
||||
}
|
||||
|
||||
static void SDLTest_PasteScreenShot(void)
|
||||
{
|
||||
const char *image_formats[] = {
|
||||
"image/bmp",
|
||||
"image/png",
|
||||
"image/tiff",
|
||||
};
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < SDL_arraysize(image_formats); ++i) {
|
||||
size_t size;
|
||||
void *data = SDL_GetClipboardData(image_formats[i], &size);
|
||||
if (data) {
|
||||
char filename[16];
|
||||
SDL_RWops *file;
|
||||
|
||||
SDL_snprintf(filename, sizeof(filename), "clipboard.%s", image_formats[i] + 6);
|
||||
file = SDL_RWFromFile(filename, "w");
|
||||
if (file) {
|
||||
SDL_Log("Writing clipboard image to %s", filename);
|
||||
SDL_RWwrite(file, data, size);
|
||||
SDL_RWclose(file);
|
||||
}
|
||||
SDL_free(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
SDL_Log("No supported screenshot data in the clipboard");
|
||||
}
|
||||
|
||||
static void FullscreenTo(SDLTest_CommonState *state, int index, int windowId)
|
||||
|
@ -1974,7 +2075,7 @@ void SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done
|
|||
if (window) {
|
||||
for (i = 0; i < state->num_windows; ++i) {
|
||||
if (window == state->windows[i]) {
|
||||
SDLTest_ScreenShot(state->renderers[i]);
|
||||
SDLTest_CopyScreenShot(state->renderers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2080,12 +2181,24 @@ void SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_c:
|
||||
if (withControl) {
|
||||
/* Ctrl-C copy awesome text! */
|
||||
SDL_SetClipboardText("SDL rocks!\nYou know it!");
|
||||
SDL_Log("Copied text to clipboard\n");
|
||||
if (withShift) {
|
||||
/* Ctrl-Shift-C copy screenshot! */
|
||||
SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
|
||||
if (window) {
|
||||
for (i = 0; i < state->num_windows; ++i) {
|
||||
if (window == state->windows[i]) {
|
||||
SDLTest_CopyScreenShot(state->renderers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Ctrl-C copy awesome text! */
|
||||
SDL_SetClipboardText("SDL rocks!\nYou know it!");
|
||||
SDL_Log("Copied text to clipboard\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (withAlt) {
|
||||
/* Alt-C toggle a render clip rectangle */
|
||||
|
@ -2118,14 +2231,19 @@ void SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done
|
|||
break;
|
||||
case SDLK_v:
|
||||
if (withControl) {
|
||||
/* Ctrl-V paste awesome text! */
|
||||
char *text = SDL_GetClipboardText();
|
||||
if (*text) {
|
||||
SDL_Log("Clipboard: %s\n", text);
|
||||
if (withShift) {
|
||||
/* Ctrl-Shift-V paste screenshot! */
|
||||
SDLTest_PasteScreenShot();
|
||||
} else {
|
||||
SDL_Log("Clipboard is empty\n");
|
||||
/* Ctrl-V paste awesome text! */
|
||||
char *text = SDL_GetClipboardText();
|
||||
if (*text) {
|
||||
SDL_Log("Clipboard: %s\n", text);
|
||||
} else {
|
||||
SDL_Log("Clipboard is empty\n");
|
||||
}
|
||||
SDL_free(text);
|
||||
}
|
||||
SDL_free(text);
|
||||
}
|
||||
break;
|
||||
case SDLK_f:
|
||||
|
|
|
@ -20,21 +20,103 @@
|
|||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_clipboard_c.h"
|
||||
#include "SDL_sysvideo.h"
|
||||
#include "../events/SDL_clipboardevents_c.h"
|
||||
|
||||
int SDL_SetClipboardData(SDL_ClipboardDataCallback callback, size_t mime_count, const char **mime_types, void *userdata)
|
||||
|
||||
void SDL_CancelClipboardData(Uint32 sequence)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
size_t i;
|
||||
|
||||
if (sequence != _this->clipboard_sequence) {
|
||||
/* This clipboard data was already canceled */
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_SendClipboardCancelled(_this->clipboard_userdata);
|
||||
|
||||
if (_this->clipboard_cleanup) {
|
||||
_this->clipboard_cleanup(_this->clipboard_userdata);
|
||||
}
|
||||
|
||||
if (_this->clipboard_mime_types) {
|
||||
for (i = 0; i < _this->num_clipboard_mime_types; ++i) {
|
||||
SDL_free(_this->clipboard_mime_types[i]);
|
||||
}
|
||||
SDL_free(_this->clipboard_mime_types);
|
||||
_this->clipboard_mime_types = NULL;
|
||||
_this->num_clipboard_mime_types = 0;
|
||||
}
|
||||
|
||||
_this->clipboard_callback = NULL;
|
||||
_this->clipboard_cleanup = NULL;
|
||||
_this->clipboard_userdata = NULL;
|
||||
}
|
||||
|
||||
int SDL_SetClipboardData(SDL_ClipboardDataCallback callback, SDL_ClipboardCleanupCallback cleanup, void *userdata, const char **mime_types, size_t num_mime_types)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
size_t i;
|
||||
|
||||
if (_this == NULL) {
|
||||
return SDL_SetError("Video subsystem must be initialized to set clipboard text");
|
||||
}
|
||||
|
||||
if (_this->SetClipboardData) {
|
||||
return _this->SetClipboardData(_this, callback, mime_count, mime_types, userdata);
|
||||
} else {
|
||||
return SDL_Unsupported();
|
||||
/* Parameter validation */
|
||||
if (!((callback && mime_types && num_mime_types > 0) ||
|
||||
(!callback && !mime_types && num_mime_types == 0))) {
|
||||
return SDL_SetError("Invalid parameters");
|
||||
}
|
||||
|
||||
if (!callback && !_this->clipboard_callback) {
|
||||
/* Nothing to do, don't modify the system clipboard */
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_CancelClipboardData(_this->clipboard_sequence);
|
||||
|
||||
++_this->clipboard_sequence;
|
||||
if (!_this->clipboard_sequence) {
|
||||
_this->clipboard_sequence = 1;
|
||||
}
|
||||
_this->clipboard_callback = callback;
|
||||
_this->clipboard_cleanup = cleanup;
|
||||
_this->clipboard_userdata = userdata;
|
||||
|
||||
if (mime_types && num_mime_types > 0) {
|
||||
size_t num_allocated = 0;
|
||||
|
||||
_this->clipboard_mime_types = (char **)SDL_malloc(num_mime_types * sizeof(char *));
|
||||
if (_this->clipboard_mime_types) {
|
||||
for (i = 0; i < num_mime_types; ++i) {
|
||||
_this->clipboard_mime_types[i] = SDL_strdup(mime_types[i]);
|
||||
if (_this->clipboard_mime_types[i]) {
|
||||
++num_allocated;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num_allocated < num_mime_types) {
|
||||
SDL_ClearClipboardData();
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
_this->num_clipboard_mime_types = num_mime_types;
|
||||
}
|
||||
|
||||
if (_this->SetClipboardData) {
|
||||
if (_this->SetClipboardData(_this) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_SendClipboardUpdate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SDL_ClearClipboardData(void)
|
||||
{
|
||||
return SDL_SetClipboardData(NULL, NULL, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
int SDL_SetClipboardText(const char *text)
|
||||
|
@ -49,12 +131,16 @@ int SDL_SetClipboardText(const char *text)
|
|||
text = "";
|
||||
}
|
||||
if (_this->SetClipboardText) {
|
||||
return _this->SetClipboardText(_this, text);
|
||||
if (_this->SetClipboardText(_this, text) < 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
SDL_free(_this->clipboard_text);
|
||||
_this->clipboard_text = SDL_strdup(text);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_SendClipboardUpdate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SDL_SetPrimarySelectionText(const char *text)
|
||||
|
@ -69,27 +155,55 @@ int SDL_SetPrimarySelectionText(const char *text)
|
|||
text = "";
|
||||
}
|
||||
if (_this->SetPrimarySelectionText) {
|
||||
return _this->SetPrimarySelectionText(_this, text);
|
||||
if (_this->SetPrimarySelectionText(_this, text) < 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
SDL_free(_this->primary_selection_text);
|
||||
_this->primary_selection_text = SDL_strdup(text);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_SendClipboardUpdate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *SDL_GetClipboardData(size_t *length, const char *mime_type)
|
||||
void *SDL_GetClipboardData(const char *mime_type, size_t *size)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
void *data = NULL;
|
||||
|
||||
if (_this == NULL) {
|
||||
SDL_SetError("Video subsystem must be initialized to get clipboard data");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (_this->GetClipboardData) {
|
||||
return _this->GetClipboardData(_this, length, mime_type);
|
||||
} else {
|
||||
if (!mime_type) {
|
||||
SDL_InvalidParamError("mime_type");
|
||||
return NULL;
|
||||
}
|
||||
if (!size) {
|
||||
SDL_InvalidParamError("size");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (_this->GetClipboardData) {
|
||||
data = _this->GetClipboardData(_this, mime_type, size);
|
||||
} else if (_this->clipboard_callback) {
|
||||
const void *provided_data = _this->clipboard_callback(_this->clipboard_userdata, mime_type, size);
|
||||
if (provided_data) {
|
||||
/* Make a copy of it for the caller */
|
||||
data = SDL_malloc(*size);
|
||||
if (data) {
|
||||
SDL_memcpy(data, provided_data, *size);
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!data) {
|
||||
*size = 0;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
char *SDL_GetClipboardText(void)
|
||||
|
@ -135,15 +249,28 @@ char *SDL_GetPrimarySelectionText(void)
|
|||
SDL_bool SDL_HasClipboardData(const char *mime_type)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
size_t i;
|
||||
|
||||
if (_this == NULL) {
|
||||
SDL_SetError("Video subsystem must be initialized to check clipboard data");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (!mime_type) {
|
||||
SDL_InvalidParamError("mime_type");
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
if (_this->HasClipboardData) {
|
||||
return _this->HasClipboardData(_this, mime_type);
|
||||
} else {
|
||||
for (i = 0; i < _this->num_clipboard_mime_types; ++i) {
|
||||
if (SDL_strcmp(mime_type, _this->clipboard_mime_types[i]) == 0) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool SDL_HasClipboardText(void)
|
||||
|
@ -177,26 +304,11 @@ SDL_bool SDL_HasPrimarySelectionText(void)
|
|||
|
||||
if (_this->HasPrimarySelectionText) {
|
||||
return _this->HasPrimarySelectionText(_this);
|
||||
} else {
|
||||
if (_this->primary_selection_text && _this->primary_selection_text[0] != '\0') {
|
||||
return SDL_TRUE;
|
||||
} else {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (_this->primary_selection_text && _this->primary_selection_text[0] != '\0') {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
void *SDL_GetClipboardUserdata(void)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
|
||||
if (_this == NULL) {
|
||||
SDL_SetError("Video subsystem must be initialized to check clipboard userdata");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (_this->GetClipboardUserdata) {
|
||||
return _this->GetClipboardUserdata(_this);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2023 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"
|
||||
|
||||
#ifndef SDL_clipboard_c_h_
|
||||
#define SDL_clipboard_c_h_
|
||||
|
||||
/* Cancel the clipboard data callback, called internally for cleanup */
|
||||
extern void SDL_CancelClipboardData(Uint32 sequence);
|
||||
|
||||
#endif /* SDL_clipboard_c_h_ */
|
|
@ -338,11 +338,9 @@ struct SDL_VideoDevice
|
|||
int (*SetPrimarySelectionText)(SDL_VideoDevice *_this, const char *text);
|
||||
char *(*GetPrimarySelectionText)(SDL_VideoDevice *_this);
|
||||
SDL_bool (*HasPrimarySelectionText)(SDL_VideoDevice *_this);
|
||||
int (*SetClipboardData)(SDL_VideoDevice *_this, SDL_ClipboardDataCallback callback, size_t mime_count,
|
||||
const char **mime_types, void *userdata);
|
||||
void *(*GetClipboardData)(SDL_VideoDevice *_this, size_t *len, const char *mime_type);
|
||||
int (*SetClipboardData)(SDL_VideoDevice *_this);
|
||||
void *(*GetClipboardData)(SDL_VideoDevice *_this, const char *mime_type, size_t *size);
|
||||
SDL_bool (*HasClipboardData)(SDL_VideoDevice *_this, const char *mime_type);
|
||||
void *(*GetClipboardUserdata)(SDL_VideoDevice *_this);
|
||||
|
||||
/* MessageBox */
|
||||
int (*ShowMessageBox)(SDL_VideoDevice *_this, const SDL_MessageBoxData *messageboxdata, int *buttonid);
|
||||
|
@ -367,6 +365,12 @@ struct SDL_VideoDevice
|
|||
SDL_Window *grabbed_window;
|
||||
Uint8 window_magic;
|
||||
SDL_WindowID next_object_id;
|
||||
Uint32 clipboard_sequence;
|
||||
SDL_ClipboardDataCallback clipboard_callback;
|
||||
SDL_ClipboardCleanupCallback clipboard_cleanup;
|
||||
void *clipboard_userdata;
|
||||
char **clipboard_mime_types;
|
||||
size_t num_clipboard_mime_types;
|
||||
char *clipboard_text;
|
||||
char *primary_selection_text;
|
||||
SDL_bool setting_display_mode;
|
||||
|
|
|
@ -3695,6 +3695,9 @@ void SDL_VideoQuit(void)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Make sure we don't try to serve clipboard data after this */
|
||||
SDL_ClearClipboardData();
|
||||
|
||||
/* Halt event processing before doing anything else */
|
||||
SDL_QuitTouch();
|
||||
SDL_QuitMouse();
|
||||
|
|
|
@ -30,10 +30,8 @@ extern int Cocoa_SetClipboardText(SDL_VideoDevice *_this, const char *text);
|
|||
extern char *Cocoa_GetClipboardText(SDL_VideoDevice *_this);
|
||||
extern SDL_bool Cocoa_HasClipboardText(SDL_VideoDevice *_this);
|
||||
extern void Cocoa_CheckClipboardUpdate(SDL_CocoaVideoData *data);
|
||||
extern void *Cocoa_GetClipboardData(SDL_VideoDevice *_this, size_t *len, const char *mime_type);
|
||||
extern int Cocoa_SetClipboardData(SDL_VideoDevice *_this);
|
||||
extern void *Cocoa_GetClipboardData(SDL_VideoDevice *_this, const char *mime_type, size_t *size);
|
||||
extern SDL_bool Cocoa_HasClipboardData(SDL_VideoDevice *_this, const char *mime_type);
|
||||
extern int Cocoa_SetClipboardData(SDL_VideoDevice *_this, SDL_ClipboardDataCallback callback, size_t mime_count,
|
||||
const char **mime_types, void *userdata);
|
||||
|
||||
|
||||
#endif /* SDL_cocoaclipboard_h_ */
|
||||
|
|
|
@ -57,10 +57,10 @@ provideDataForType:(NSPasteboardType)type
|
|||
@autoreleasepool {
|
||||
size_t size = 0;
|
||||
CFStringRef mimeType;
|
||||
void *callbackData;
|
||||
const void *callbackData;
|
||||
NSData *data;
|
||||
mimeType = UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)type, kUTTagClassMIMEType);
|
||||
callbackData = m_callback(&size, [(__bridge NSString *)mimeType UTF8String], m_userdata);
|
||||
callbackData = m_callback(m_userdata, [(__bridge NSString *)mimeType UTF8String], &size);
|
||||
CFRelease(mimeType);
|
||||
if (callbackData == NULL || size == 0) {
|
||||
return;
|
||||
|
@ -149,62 +149,19 @@ void Cocoa_CheckClipboardUpdate(SDL_CocoaVideoData *data)
|
|||
}
|
||||
}
|
||||
|
||||
void *Cocoa_GetClipboardData(SDL_VideoDevice *_this, size_t *len, const char *mime_type)
|
||||
{
|
||||
@autoreleasepool {
|
||||
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
|
||||
NSData *itemData;
|
||||
void *data;
|
||||
*len = 0;
|
||||
for (NSPasteboardItem *item in [pasteboard pasteboardItems]) {
|
||||
CFStringRef mimeType = CFStringCreateWithCString(NULL, mime_type, kCFStringEncodingUTF8);
|
||||
CFStringRef utiType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL);
|
||||
CFRelease(mimeType);
|
||||
itemData = [item dataForType: (__bridge NSString *)utiType];
|
||||
CFRelease(utiType);
|
||||
if (itemData != nil) {
|
||||
*len = (size_t)[itemData length];
|
||||
data = SDL_malloc(*len);
|
||||
[itemData getBytes: data length: *len];
|
||||
return data;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool Cocoa_HasClipboardData(SDL_VideoDevice *_this, const char *mime_type)
|
||||
{
|
||||
|
||||
SDL_bool result = SDL_FALSE;
|
||||
@autoreleasepool {
|
||||
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
|
||||
CFStringRef mimeType = CFStringCreateWithCString(NULL, mime_type, kCFStringEncodingUTF8);
|
||||
CFStringRef utiType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL);
|
||||
CFRelease(mimeType);
|
||||
if ([pasteboard canReadItemWithDataConformingToTypes: @[(__bridge NSString *)utiType]]) {
|
||||
result = SDL_TRUE;
|
||||
}
|
||||
CFRelease(utiType);
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
int Cocoa_SetClipboardData(SDL_VideoDevice *_this, SDL_ClipboardDataCallback callback, size_t mime_count,
|
||||
const char **mime_types, void *userdata)
|
||||
int Cocoa_SetClipboardData(SDL_VideoDevice *_this)
|
||||
{
|
||||
@autoreleasepool {
|
||||
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
|
||||
NSPasteboardItem *newItem = [NSPasteboardItem new];
|
||||
NSMutableArray *utiTypes = [NSMutableArray new];
|
||||
Cocoa_PasteboardDataProvider *provider = [[Cocoa_PasteboardDataProvider alloc] initWith: callback userData: userdata];
|
||||
Cocoa_PasteboardDataProvider *provider = [[Cocoa_PasteboardDataProvider alloc] initWith: _this->clipboard_callback userData: _this->clipboard_userdata];
|
||||
BOOL itemResult = FALSE;
|
||||
BOOL writeResult = FALSE;
|
||||
SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->driverdata;
|
||||
|
||||
for (int i = 0; i < mime_count; i++) {
|
||||
CFStringRef mimeType = CFStringCreateWithCString(NULL, mime_types[i], kCFStringEncodingUTF8);
|
||||
for (int i = 0; i < _this->num_clipboard_mime_types; i++) {
|
||||
CFStringRef mimeType = CFStringCreateWithCString(NULL, _this->clipboard_mime_types[i], kCFStringEncodingUTF8);
|
||||
CFStringRef utiType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL);
|
||||
CFRelease(mimeType);
|
||||
|
||||
|
@ -226,4 +183,50 @@ int Cocoa_SetClipboardData(SDL_VideoDevice *_this, SDL_ClipboardDataCallback cal
|
|||
return 0;
|
||||
}
|
||||
|
||||
void *Cocoa_GetClipboardData(SDL_VideoDevice *_this, const char *mime_type, size_t *size)
|
||||
{
|
||||
@autoreleasepool {
|
||||
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
|
||||
void *data = NULL;
|
||||
*size = 0;
|
||||
for (NSPasteboardItem *item in [pasteboard pasteboardItems]) {
|
||||
NSData *itemData;
|
||||
CFStringRef mimeType = CFStringCreateWithCString(NULL, mime_type, kCFStringEncodingUTF8);
|
||||
CFStringRef utiType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL);
|
||||
CFRelease(mimeType);
|
||||
itemData = [item dataForType: (__bridge NSString *)utiType];
|
||||
CFRelease(utiType);
|
||||
if (itemData != nil) {
|
||||
NSUInteger length = [itemData length];
|
||||
*size = (size_t)length;
|
||||
data = SDL_malloc(*size);
|
||||
if (data) {
|
||||
[itemData getBytes: data length: length];
|
||||
} else {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_bool Cocoa_HasClipboardData(SDL_VideoDevice *_this, const char *mime_type)
|
||||
{
|
||||
SDL_bool result = SDL_FALSE;
|
||||
@autoreleasepool {
|
||||
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
|
||||
CFStringRef mimeType = CFStringCreateWithCString(NULL, mime_type, kCFStringEncodingUTF8);
|
||||
CFStringRef utiType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL);
|
||||
CFRelease(mimeType);
|
||||
if ([pasteboard canReadItemWithDataConformingToTypes: @[(__bridge NSString *)utiType]]) {
|
||||
result = SDL_TRUE;
|
||||
}
|
||||
CFRelease(utiType);
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_COCOA */
|
||||
|
|
|
@ -175,9 +175,9 @@ static SDL_VideoDevice *Cocoa_CreateDevice(void)
|
|||
device->GetClipboardText = Cocoa_GetClipboardText;
|
||||
device->HasClipboardText = Cocoa_HasClipboardText;
|
||||
|
||||
device->SetClipboardData = Cocoa_SetClipboardData;
|
||||
device->GetClipboardData = Cocoa_GetClipboardData;
|
||||
device->HasClipboardData = Cocoa_HasClipboardData;
|
||||
device->SetClipboardData = Cocoa_SetClipboardData;
|
||||
|
||||
device->free = Cocoa_DeleteDevice;
|
||||
|
||||
|
|
|
@ -27,8 +27,7 @@
|
|||
#include "SDL_waylandevents_c.h"
|
||||
#include "SDL_waylandclipboard.h"
|
||||
|
||||
int Wayland_SetClipboardData(SDL_VideoDevice *_this, SDL_ClipboardDataCallback callback, size_t mime_count, const char **mime_types,
|
||||
void *userdata)
|
||||
int Wayland_SetClipboardData(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *video_data = NULL;
|
||||
SDL_WaylandDataDevice *data_device = NULL;
|
||||
|
@ -39,11 +38,11 @@ int Wayland_SetClipboardData(SDL_VideoDevice *_this, SDL_ClipboardDataCallback c
|
|||
if (video_data->input != NULL && video_data->input->data_device != NULL) {
|
||||
data_device = video_data->input->data_device;
|
||||
|
||||
if (callback && mime_types) {
|
||||
if (_this->clipboard_callback && _this->clipboard_mime_types) {
|
||||
SDL_WaylandDataSource *source = Wayland_data_source_create(_this);
|
||||
Wayland_data_source_set_callback(source, callback, userdata, SDL_FALSE);
|
||||
Wayland_data_source_set_callback(source, _this->clipboard_callback, _this->clipboard_userdata, _this->clipboard_sequence);
|
||||
|
||||
status = Wayland_data_device_set_selection(data_device, source, mime_count, mime_types);
|
||||
status = Wayland_data_device_set_selection(data_device, source, (const char **)_this->clipboard_mime_types, _this->num_clipboard_mime_types);
|
||||
if (status != 0) {
|
||||
Wayland_data_source_destroy(source);
|
||||
}
|
||||
|
@ -64,29 +63,22 @@ static const char *text_mime_types[TEXT_MIME_TYPES_LEN] = {
|
|||
"STRING",
|
||||
};
|
||||
|
||||
static void *Wayland_ClipboardTextCallback(size_t *length, const char *mime_type, void *userdata)
|
||||
static const void *Wayland_ClipboardTextCallback(void *userdata, const char *mime_type, size_t *length)
|
||||
{
|
||||
void *data = NULL;
|
||||
SDL_bool valid_mime_type = SDL_FALSE;
|
||||
const void *data = NULL;
|
||||
|
||||
*length = 0;
|
||||
|
||||
if (userdata == NULL) {
|
||||
return data;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < TEXT_MIME_TYPES_LEN; ++i) {
|
||||
if (SDL_strcmp(mime_type, text_mime_types[i]) == 0) {
|
||||
valid_mime_type = SDL_TRUE;
|
||||
break;
|
||||
if (userdata) {
|
||||
for (size_t i = 0; i < TEXT_MIME_TYPES_LEN; ++i) {
|
||||
if (SDL_strcmp(mime_type, text_mime_types[i]) == 0) {
|
||||
char *text = userdata;
|
||||
*length = SDL_strlen(text);
|
||||
data = userdata;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_mime_type) {
|
||||
char *text = userdata;
|
||||
*length = SDL_strlen(text);
|
||||
data = userdata;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -106,9 +98,9 @@ int Wayland_SetClipboardText(SDL_VideoDevice *_this, const char *text)
|
|||
|
||||
if (text[0] != '\0') {
|
||||
SDL_WaylandDataSource *source = Wayland_data_source_create(_this);
|
||||
Wayland_data_source_set_callback(source, Wayland_ClipboardTextCallback, SDL_strdup(text), SDL_TRUE);
|
||||
Wayland_data_source_set_callback(source, Wayland_ClipboardTextCallback, SDL_strdup(text), 0);
|
||||
|
||||
status = Wayland_data_device_set_selection(data_device, source, TEXT_MIME_TYPES_LEN, text_mime_types);
|
||||
status = Wayland_data_device_set_selection(data_device, source, text_mime_types, TEXT_MIME_TYPES_LEN);
|
||||
if (status != 0) {
|
||||
Wayland_data_source_destroy(source);
|
||||
}
|
||||
|
@ -140,8 +132,8 @@ int Wayland_SetPrimarySelectionText(SDL_VideoDevice *_this, const char *text)
|
|||
|
||||
status = Wayland_primary_selection_device_set_selection(primary_selection_device,
|
||||
source,
|
||||
TEXT_MIME_TYPES_LEN,
|
||||
text_mime_types);
|
||||
text_mime_types,
|
||||
TEXT_MIME_TYPES_LEN);
|
||||
if (status != 0) {
|
||||
Wayland_primary_selection_source_destroy(source);
|
||||
}
|
||||
|
@ -154,7 +146,7 @@ int Wayland_SetPrimarySelectionText(SDL_VideoDevice *_this, const char *text)
|
|||
return status;
|
||||
}
|
||||
|
||||
void *Wayland_GetClipboardData(SDL_VideoDevice *_this, size_t *length, const char *mime_type)
|
||||
void *Wayland_GetClipboardData(SDL_VideoDevice *_this, const char *mime_type, size_t *length)
|
||||
{
|
||||
SDL_VideoData *video_data = NULL;
|
||||
SDL_WaylandDataDevice *data_device = NULL;
|
||||
|
@ -164,13 +156,10 @@ void *Wayland_GetClipboardData(SDL_VideoDevice *_this, size_t *length, const cha
|
|||
video_data = _this->driverdata;
|
||||
if (video_data->input != NULL && video_data->input->data_device != NULL) {
|
||||
data_device = video_data->input->data_device;
|
||||
if (data_device->selection_source != NULL) {
|
||||
buffer = Wayland_data_source_get_data(data_device->selection_source,
|
||||
length, mime_type, SDL_FALSE);
|
||||
} else if (Wayland_data_offer_has_mime(
|
||||
data_device->selection_offer, mime_type)) {
|
||||
buffer = Wayland_data_offer_receive(data_device->selection_offer,
|
||||
length, mime_type, SDL_FALSE);
|
||||
if (data_device->selection_source && data_device->selection_source->userdata.sequence != 0) {
|
||||
buffer = Wayland_data_source_get_data(data_device->selection_source, mime_type, length, SDL_FALSE);
|
||||
} else if (Wayland_data_offer_has_mime(data_device->selection_offer, mime_type)) {
|
||||
buffer = Wayland_data_offer_receive(data_device->selection_offer, mime_type, length, SDL_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,12 +180,12 @@ char *Wayland_GetClipboardText(SDL_VideoDevice *_this)
|
|||
video_data = _this->driverdata;
|
||||
if (video_data->input != NULL && video_data->input->data_device != NULL) {
|
||||
data_device = video_data->input->data_device;
|
||||
if (data_device->selection_source != NULL) {
|
||||
text = Wayland_data_source_get_data(data_device->selection_source, &length, TEXT_MIME, SDL_TRUE);
|
||||
if (data_device->selection_source && data_device->selection_source->userdata.sequence == 0) {
|
||||
text = Wayland_data_source_get_data(data_device->selection_source, TEXT_MIME, &length, SDL_TRUE);
|
||||
} else if (Wayland_data_offer_has_mime(
|
||||
data_device->selection_offer, TEXT_MIME)) {
|
||||
text = Wayland_data_offer_receive(data_device->selection_offer,
|
||||
&length, TEXT_MIME, SDL_TRUE);
|
||||
TEXT_MIME, &length, SDL_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -223,11 +212,11 @@ char *Wayland_GetPrimarySelectionText(SDL_VideoDevice *_this)
|
|||
if (video_data->input != NULL && video_data->input->primary_selection_device != NULL) {
|
||||
primary_selection_device = video_data->input->primary_selection_device;
|
||||
if (primary_selection_device->selection_source != NULL) {
|
||||
text = Wayland_primary_selection_source_get_data(primary_selection_device->selection_source, &length, TEXT_MIME, SDL_TRUE);
|
||||
text = Wayland_primary_selection_source_get_data(primary_selection_device->selection_source, TEXT_MIME, &length, SDL_TRUE);
|
||||
} else if (Wayland_primary_selection_offer_has_mime(
|
||||
primary_selection_device->selection_offer, TEXT_MIME)) {
|
||||
text = Wayland_primary_selection_offer_receive(primary_selection_device->selection_offer,
|
||||
&length, TEXT_MIME, SDL_TRUE);
|
||||
TEXT_MIME, &length, SDL_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -250,8 +239,8 @@ static SDL_bool HasClipboardData(SDL_VideoDevice *_this, const char *mime_type)
|
|||
data_device = video_data->input->data_device;
|
||||
if (data_device->selection_source != NULL) {
|
||||
size_t length = 0;
|
||||
char *buffer = Wayland_data_source_get_data(data_device->selection_source, &length, mime_type, SDL_TRUE);
|
||||
result = buffer != NULL;
|
||||
char *buffer = Wayland_data_source_get_data(data_device->selection_source, mime_type, &length, SDL_TRUE);
|
||||
result = (buffer ? SDL_TRUE : SDL_FALSE);
|
||||
SDL_free(buffer);
|
||||
} else {
|
||||
result = Wayland_data_offer_has_mime(data_device->selection_offer, mime_type);
|
||||
|
@ -285,7 +274,7 @@ SDL_bool Wayland_HasPrimarySelectionText(SDL_VideoDevice *_this)
|
|||
if (primary_selection_device->selection_source != NULL) {
|
||||
size_t length = 0;
|
||||
char *buffer = Wayland_primary_selection_source_get_data(primary_selection_device->selection_source,
|
||||
&length, TEXT_MIME, SDL_TRUE);
|
||||
TEXT_MIME, &length, SDL_TRUE);
|
||||
result = buffer != NULL;
|
||||
SDL_free(buffer);
|
||||
} else {
|
||||
|
@ -297,22 +286,4 @@ SDL_bool Wayland_HasPrimarySelectionText(SDL_VideoDevice *_this)
|
|||
return result;
|
||||
}
|
||||
|
||||
void *Wayland_GetClipboardUserdata(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *video_data = NULL;
|
||||
SDL_WaylandDataDevice *data_device = NULL;
|
||||
void *data = NULL;
|
||||
|
||||
video_data = _this->driverdata;
|
||||
if (video_data->input != NULL && video_data->input->data_device != NULL) {
|
||||
data_device = video_data->input->data_device;
|
||||
if (data_device->selection_source != NULL
|
||||
&& data_device->selection_source->userdata.internal == SDL_FALSE) {
|
||||
data = data_device->selection_source->userdata.data;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_WAYLAND */
|
||||
|
|
|
@ -23,9 +23,8 @@
|
|||
#ifndef SDL_waylandclipboard_h_
|
||||
#define SDL_waylandclipboard_h_
|
||||
|
||||
extern int Wayland_SetClipboardData(SDL_VideoDevice *_this, SDL_ClipboardDataCallback callback, size_t mime_count,
|
||||
const char **mime_types, void *userdata);
|
||||
extern void *Wayland_GetClipboardData(SDL_VideoDevice *_this, size_t *length, const char *mime_type);
|
||||
extern int Wayland_SetClipboardData(SDL_VideoDevice *_this);
|
||||
extern void *Wayland_GetClipboardData(SDL_VideoDevice *_this, const char *mime_type, size_t *length);
|
||||
extern SDL_bool Wayland_HasClipboardData(SDL_VideoDevice *_this, const char *mime_type);
|
||||
extern int Wayland_SetClipboardText(SDL_VideoDevice *_this, const char *text);
|
||||
extern char *Wayland_GetClipboardText(SDL_VideoDevice *_this);
|
||||
|
@ -33,6 +32,5 @@ extern SDL_bool Wayland_HasClipboardText(SDL_VideoDevice *_this);
|
|||
extern int Wayland_SetPrimarySelectionText(SDL_VideoDevice *_this, const char *text);
|
||||
extern char *Wayland_GetPrimarySelectionText(SDL_VideoDevice *_this);
|
||||
extern SDL_bool Wayland_HasPrimarySelectionText(SDL_VideoDevice *_this);
|
||||
extern void *Wayland_GetClipboardUserdata(SDL_VideoDevice *_this);
|
||||
|
||||
#endif /* SDL_waylandclipboard_h_ */
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "../../core/unix/SDL_poll.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "../SDL_clipboard_c.h"
|
||||
|
||||
#include "SDL_waylandvideo.h"
|
||||
#include "SDL_waylanddatamanager.h"
|
||||
|
@ -218,7 +219,7 @@ static void mime_data_list_free(struct wl_list *list)
|
|||
}
|
||||
}
|
||||
|
||||
static size_t Wayland_send_data(void *data, size_t length, int fd)
|
||||
static size_t Wayland_send_data(const void *data, size_t length, int fd)
|
||||
{
|
||||
size_t result = 0;
|
||||
|
||||
|
@ -234,11 +235,11 @@ static size_t Wayland_send_data(void *data, size_t length, int fd)
|
|||
|
||||
ssize_t Wayland_data_source_send(SDL_WaylandDataSource *source, const char *mime_type, int fd)
|
||||
{
|
||||
void *data = NULL;
|
||||
const void *data = NULL;
|
||||
size_t length = 0;
|
||||
|
||||
if (source->callback) {
|
||||
data = source->callback(&length, mime_type, source->userdata.data);
|
||||
data = source->callback(source->userdata.data, mime_type, &length);
|
||||
}
|
||||
|
||||
return Wayland_send_data(data, length, fd);
|
||||
|
@ -246,11 +247,11 @@ ssize_t Wayland_data_source_send(SDL_WaylandDataSource *source, const char *mime
|
|||
|
||||
ssize_t Wayland_primary_selection_source_send(SDL_WaylandPrimarySelectionSource *source, const char *mime_type, int fd)
|
||||
{
|
||||
void *data = NULL;
|
||||
const void *data = NULL;
|
||||
size_t length = 0;
|
||||
|
||||
if (source->callback) {
|
||||
data = source->callback(&length, mime_type, source->userdata.data);
|
||||
data = source->callback(source->userdata.data, mime_type, &length);
|
||||
}
|
||||
|
||||
return Wayland_send_data(data, length, fd);
|
||||
|
@ -259,12 +260,12 @@ ssize_t Wayland_primary_selection_source_send(SDL_WaylandPrimarySelectionSource
|
|||
void Wayland_data_source_set_callback(SDL_WaylandDataSource *source,
|
||||
SDL_ClipboardDataCallback callback,
|
||||
void *userdata,
|
||||
SDL_bool internal)
|
||||
Uint32 sequence)
|
||||
{
|
||||
if (source != NULL) {
|
||||
source->callback = callback;
|
||||
source->userdata.internal = internal;
|
||||
source->userdata.data = userdata;
|
||||
source->callback = callback;
|
||||
source->userdata.sequence = sequence;
|
||||
source->userdata.data = userdata;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,12 +277,12 @@ int Wayland_primary_selection_source_set_callback(SDL_WaylandPrimarySelectionSou
|
|||
return SDL_InvalidParamError("source");
|
||||
}
|
||||
source->callback = callback;
|
||||
source->userdata.internal = SDL_TRUE;
|
||||
source->userdata.sequence = 0;
|
||||
source->userdata.data = userdata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *Wayland_clone_data_buffer(void *buffer, size_t *len, SDL_bool null_terminate)
|
||||
static void *Wayland_clone_data_buffer(const void *buffer, size_t *len, SDL_bool null_terminate)
|
||||
{
|
||||
void *clone = NULL;
|
||||
if (*len > 0 && buffer != NULL) {
|
||||
|
@ -307,17 +308,17 @@ static void *Wayland_clone_data_buffer(void *buffer, size_t *len, SDL_bool null_
|
|||
}
|
||||
|
||||
void *Wayland_data_source_get_data(SDL_WaylandDataSource *source,
|
||||
size_t *length, const char *mime_type,
|
||||
const char *mime_type, size_t *length,
|
||||
SDL_bool null_terminate)
|
||||
{
|
||||
void *buffer = NULL;
|
||||
void *internal_buffer;
|
||||
const void *internal_buffer;
|
||||
*length = 0;
|
||||
|
||||
if (source == NULL) {
|
||||
SDL_SetError("Invalid data source");
|
||||
} else if (source->callback != NULL) {
|
||||
internal_buffer = source->callback(length, mime_type, source->userdata.data);
|
||||
internal_buffer = source->callback(source->userdata.data, mime_type, length);
|
||||
buffer = Wayland_clone_data_buffer(internal_buffer, length, null_terminate);
|
||||
}
|
||||
|
||||
|
@ -325,17 +326,17 @@ void *Wayland_data_source_get_data(SDL_WaylandDataSource *source,
|
|||
}
|
||||
|
||||
void *Wayland_primary_selection_source_get_data(SDL_WaylandPrimarySelectionSource *source,
|
||||
size_t *length, const char *mime_type,
|
||||
const char *mime_type, size_t *length,
|
||||
SDL_bool null_terminate)
|
||||
{
|
||||
void *buffer = NULL;
|
||||
void *internal_buffer;
|
||||
const void *internal_buffer;
|
||||
*length = 0;
|
||||
|
||||
if (source == NULL) {
|
||||
SDL_SetError("Invalid primary selection source");
|
||||
} else if (source->callback) {
|
||||
internal_buffer = source->callback(length, mime_type, source->userdata.data);
|
||||
internal_buffer = source->callback(source->userdata.data, mime_type, length);
|
||||
buffer = Wayland_clone_data_buffer(internal_buffer, length, null_terminate);
|
||||
}
|
||||
|
||||
|
@ -350,10 +351,10 @@ void Wayland_data_source_destroy(SDL_WaylandDataSource *source)
|
|||
data_device->selection_source = NULL;
|
||||
}
|
||||
wl_data_source_destroy(source->source);
|
||||
if (source->userdata.internal == SDL_TRUE) {
|
||||
SDL_free(source->userdata.data);
|
||||
if (source->userdata.sequence) {
|
||||
SDL_CancelClipboardData(source->userdata.sequence);
|
||||
} else {
|
||||
SDL_SendClipboardCancelled(source->userdata.data);
|
||||
SDL_free(source->userdata.data);
|
||||
}
|
||||
SDL_free(source);
|
||||
}
|
||||
|
@ -367,7 +368,7 @@ void Wayland_primary_selection_source_destroy(SDL_WaylandPrimarySelectionSource
|
|||
primary_selection_device->selection_source = NULL;
|
||||
}
|
||||
zwp_primary_selection_source_v1_destroy(source->source);
|
||||
if (source->userdata.internal == SDL_TRUE) {
|
||||
if (source->userdata.sequence == 0) {
|
||||
SDL_free(source->userdata.data);
|
||||
}
|
||||
SDL_free(source);
|
||||
|
@ -375,7 +376,7 @@ void Wayland_primary_selection_source_destroy(SDL_WaylandPrimarySelectionSource
|
|||
}
|
||||
|
||||
void *Wayland_data_offer_receive(SDL_WaylandDataOffer *offer,
|
||||
size_t *length, const char *mime_type,
|
||||
const char *mime_type, size_t *length,
|
||||
SDL_bool null_terminate)
|
||||
{
|
||||
SDL_WaylandDataDevice *data_device = NULL;
|
||||
|
@ -409,7 +410,7 @@ void *Wayland_data_offer_receive(SDL_WaylandDataOffer *offer,
|
|||
}
|
||||
|
||||
void *Wayland_primary_selection_offer_receive(SDL_WaylandPrimarySelectionOffer *offer,
|
||||
size_t *length, const char *mime_type,
|
||||
const char *mime_type, size_t *length,
|
||||
SDL_bool null_terminate)
|
||||
{
|
||||
SDL_WaylandPrimarySelectionDevice *primary_selection_device = NULL;
|
||||
|
@ -525,8 +526,8 @@ int Wayland_primary_selection_device_clear_selection(SDL_WaylandPrimarySelection
|
|||
|
||||
int Wayland_data_device_set_selection(SDL_WaylandDataDevice *data_device,
|
||||
SDL_WaylandDataSource *source,
|
||||
size_t mime_count,
|
||||
const char **mime_types)
|
||||
const char **mime_types,
|
||||
size_t mime_count)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
|
@ -567,8 +568,8 @@ int Wayland_data_device_set_selection(SDL_WaylandDataDevice *data_device,
|
|||
|
||||
int Wayland_primary_selection_device_set_selection(SDL_WaylandPrimarySelectionDevice *primary_selection_device,
|
||||
SDL_WaylandPrimarySelectionSource *source,
|
||||
size_t mime_count,
|
||||
const char **mime_types)
|
||||
const char **mime_types,
|
||||
size_t mime_count)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ typedef struct
|
|||
|
||||
typedef struct SDL_WaylandUserdata
|
||||
{
|
||||
SDL_bool internal;
|
||||
Uint32 sequence;
|
||||
void *data;
|
||||
} SDL_WaylandUserdata;
|
||||
|
||||
|
@ -111,29 +111,29 @@ extern ssize_t Wayland_primary_selection_source_send(SDL_WaylandPrimarySelection
|
|||
extern void Wayland_data_source_set_callback(SDL_WaylandDataSource *source,
|
||||
SDL_ClipboardDataCallback callback,
|
||||
void *userdata,
|
||||
SDL_bool internal);
|
||||
Uint32 sequence);
|
||||
extern int Wayland_primary_selection_source_set_callback(SDL_WaylandPrimarySelectionSource *source,
|
||||
SDL_ClipboardDataCallback callback,
|
||||
void *userdata);
|
||||
extern void *Wayland_data_source_get_data(SDL_WaylandDataSource *source,
|
||||
size_t *length,
|
||||
const char *mime_type,
|
||||
size_t *length,
|
||||
SDL_bool null_terminate);
|
||||
extern void *Wayland_primary_selection_source_get_data(SDL_WaylandPrimarySelectionSource *source,
|
||||
size_t *length,
|
||||
const char *mime_type,
|
||||
size_t *length,
|
||||
SDL_bool null_terminate);
|
||||
extern void Wayland_data_source_destroy(SDL_WaylandDataSource *source);
|
||||
extern void Wayland_primary_selection_source_destroy(SDL_WaylandPrimarySelectionSource *source);
|
||||
|
||||
/* Wayland Data / Primary Selection Offer - (Receiving) */
|
||||
extern void *Wayland_data_offer_receive(SDL_WaylandDataOffer *offer,
|
||||
size_t *length,
|
||||
const char *mime_type,
|
||||
size_t *length,
|
||||
SDL_bool null_terminate);
|
||||
extern void *Wayland_primary_selection_offer_receive(SDL_WaylandPrimarySelectionOffer *offer,
|
||||
size_t *length,
|
||||
const char *mime_type,
|
||||
size_t *length,
|
||||
SDL_bool null_terminate);
|
||||
extern SDL_bool Wayland_data_offer_has_mime(SDL_WaylandDataOffer *offer,
|
||||
const char *mime_type);
|
||||
|
@ -151,12 +151,12 @@ extern int Wayland_data_device_clear_selection(SDL_WaylandDataDevice *device);
|
|||
extern int Wayland_primary_selection_device_clear_selection(SDL_WaylandPrimarySelectionDevice *device);
|
||||
extern int Wayland_data_device_set_selection(SDL_WaylandDataDevice *device,
|
||||
SDL_WaylandDataSource *source,
|
||||
size_t mime_count,
|
||||
const char **mime_types);
|
||||
const char **mime_types,
|
||||
size_t mime_count);
|
||||
extern int Wayland_primary_selection_device_set_selection(SDL_WaylandPrimarySelectionDevice *device,
|
||||
SDL_WaylandPrimarySelectionSource *source,
|
||||
size_t mime_count,
|
||||
const char **mime_types);
|
||||
const char **mime_types,
|
||||
size_t mime_count);
|
||||
extern int Wayland_data_device_set_serial(SDL_WaylandDataDevice *device,
|
||||
uint32_t serial);
|
||||
extern int Wayland_primary_selection_device_set_serial(SDL_WaylandPrimarySelectionDevice *device,
|
||||
|
|
|
@ -1873,7 +1873,7 @@ static void data_device_handle_motion(void *data, struct wl_data_device *wl_data
|
|||
/* TODO: SDL Support more mime types */
|
||||
size_t length;
|
||||
void *buffer = Wayland_data_offer_receive(data_device->drag_offer,
|
||||
&length, FILE_MIME, SDL_TRUE);
|
||||
FILE_MIME, &length, SDL_TRUE);
|
||||
if (buffer) {
|
||||
char *saveptr = NULL;
|
||||
char *token = SDL_strtok_r((char *)buffer, "\r\n", &saveptr);
|
||||
|
@ -2022,7 +2022,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device *wl_data_d
|
|||
/* TODO: SDL Support more mime types */
|
||||
size_t length;
|
||||
void *buffer = Wayland_data_offer_receive(data_device->drag_offer,
|
||||
&length, FILE_MIME, SDL_TRUE);
|
||||
FILE_MIME, &length, SDL_TRUE);
|
||||
if (buffer) {
|
||||
char *saveptr = NULL;
|
||||
char *token = SDL_strtok_r((char *)buffer, "\r\n", &saveptr);
|
||||
|
|
|
@ -224,7 +224,6 @@ static SDL_VideoDevice *Wayland_CreateDevice(void)
|
|||
device->SetPrimarySelectionText = Wayland_SetPrimarySelectionText;
|
||||
device->GetPrimarySelectionText = Wayland_GetPrimarySelectionText;
|
||||
device->HasPrimarySelectionText = Wayland_HasPrimarySelectionText;
|
||||
device->GetClipboardUserdata = Wayland_GetClipboardUserdata;
|
||||
device->StartTextInput = Wayland_StartTextInput;
|
||||
device->StopTextInput = Wayland_StopTextInput;
|
||||
device->SetTextInputRect = Wayland_SetTextInputRect;
|
||||
|
|
|
@ -37,31 +37,24 @@ static const char *text_mime_types[TEXT_MIME_TYPES_LEN] = {
|
|||
"STRING",
|
||||
};
|
||||
|
||||
static void *X11_ClipboardTextCallback(size_t *length, const char *mime_type, void *userdata)
|
||||
static const void *X11_ClipboardTextCallback(void *userdata, const char *mime_type, size_t *length)
|
||||
{
|
||||
void *data = NULL;
|
||||
SDL_bool valid_mime_type = SDL_FALSE;
|
||||
size_t i;
|
||||
const void *data = NULL;
|
||||
|
||||
*length = 0;
|
||||
|
||||
if (userdata == NULL) {
|
||||
return data;
|
||||
}
|
||||
if (userdata) {
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < TEXT_MIME_TYPES_LEN; ++i) {
|
||||
if (SDL_strcmp(mime_type, text_mime_types[i]) == 0) {
|
||||
valid_mime_type = SDL_TRUE;
|
||||
break;
|
||||
for (i = 0; i < TEXT_MIME_TYPES_LEN; ++i) {
|
||||
if (SDL_strcmp(mime_type, text_mime_types[i]) == 0) {
|
||||
char *text = userdata;
|
||||
*length = SDL_strlen(text);
|
||||
data = userdata;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_mime_type) {
|
||||
char *text = userdata;
|
||||
*length = SDL_strlen(text);
|
||||
data = userdata;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -88,7 +81,7 @@ static Window GetWindow(SDL_VideoDevice *_this)
|
|||
}
|
||||
|
||||
static int SetSelectionData(SDL_VideoDevice *_this, Atom selection, SDL_ClipboardDataCallback callback,
|
||||
size_t mime_count, const char **mime_types, void *userdata, SDL_bool internal)
|
||||
void *userdata, const char **mime_types, size_t mime_count, Uint32 sequence)
|
||||
{
|
||||
SDL_VideoData *videodata = _this->driverdata;
|
||||
Display *display = videodata->display;
|
||||
|
@ -110,19 +103,15 @@ static int SetSelectionData(SDL_VideoDevice *_this, Atom selection, SDL_Clipboar
|
|||
clipboard_owner = X11_XGetSelectionOwner(display, selection) == window;
|
||||
|
||||
/* If we are cancelling our own data we need to clean it up */
|
||||
if (clipboard_owner) {
|
||||
if (clipboard->internal == SDL_TRUE) {
|
||||
SDL_free(clipboard->userdata);
|
||||
} else {
|
||||
SDL_SendClipboardCancelled(clipboard->userdata);
|
||||
}
|
||||
if (clipboard_owner && clipboard->sequence == 0) {
|
||||
SDL_free(clipboard->userdata);
|
||||
}
|
||||
|
||||
clipboard->callback = callback;
|
||||
clipboard->userdata = userdata;
|
||||
clipboard->mime_types = mime_types;
|
||||
clipboard->mime_count = mime_count;
|
||||
clipboard->internal = internal;
|
||||
clipboard->sequence = sequence;
|
||||
|
||||
if (!clipboard_owner) {
|
||||
X11_XSetSelectionOwner(display, selection, window, CurrentTime);
|
||||
|
@ -130,7 +119,7 @@ static int SetSelectionData(SDL_VideoDevice *_this, Atom selection, SDL_Clipboar
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void *CloneDataBuffer(void *buffer, size_t *len, SDL_bool nullterminate)
|
||||
static void *CloneDataBuffer(const void *buffer, size_t *len, SDL_bool nullterminate)
|
||||
{
|
||||
void *clone = NULL;
|
||||
if (*len > 0 && buffer != NULL) {
|
||||
|
@ -155,8 +144,8 @@ static void *CloneDataBuffer(void *buffer, size_t *len, SDL_bool nullterminate)
|
|||
return clone;
|
||||
}
|
||||
|
||||
static void *GetSelectionData(SDL_VideoDevice *_this, Atom selection_type, size_t *length,
|
||||
const char *mime_type, SDL_bool nullterminate)
|
||||
static void *GetSelectionData(SDL_VideoDevice *_this, Atom selection_type,
|
||||
const char *mime_type, size_t *length, SDL_bool nullterminate)
|
||||
{
|
||||
SDL_VideoData *videodata = _this->driverdata;
|
||||
Display *display = videodata->display;
|
||||
|
@ -174,6 +163,7 @@ static void *GetSelectionData(SDL_VideoDevice *_this, Atom selection_type, size_
|
|||
void *data = NULL;
|
||||
unsigned char *src = NULL;
|
||||
Atom XA_MIME = X11_XInternAtom(display, mime_type, False);
|
||||
Atom XA_INCR = X11_XInternAtom(display, "INCR", False);
|
||||
|
||||
*length = 0;
|
||||
|
||||
|
@ -192,8 +182,8 @@ static void *GetSelectionData(SDL_VideoDevice *_this, Atom selection_type, size_
|
|||
}
|
||||
|
||||
if (clipboard->callback) {
|
||||
src = clipboard->callback(length, mime_type, clipboard->userdata);
|
||||
data = CloneDataBuffer(src, length, nullterminate);
|
||||
const void *clipboard_data = clipboard->callback(clipboard->userdata, mime_type, length);
|
||||
data = CloneDataBuffer(clipboard_data, length, nullterminate);
|
||||
}
|
||||
} else {
|
||||
/* Request that the selection owner copy the data to our window */
|
||||
|
@ -216,8 +206,8 @@ static void *GetSelectionData(SDL_VideoDevice *_this, Atom selection_type, size_
|
|||
SDL_SetError("Selection timeout");
|
||||
/* We need to set the selection text so that next time we won't
|
||||
timeout, otherwise we will hang on every call to this function. */
|
||||
SetSelectionData(_this, selection_type, X11_ClipboardTextCallback, TEXT_MIME_TYPES_LEN,
|
||||
text_mime_types, NULL, SDL_TRUE);
|
||||
SetSelectionData(_this, selection_type, X11_ClipboardTextCallback, NULL,
|
||||
text_mime_types, TEXT_MIME_TYPES_LEN, 0);
|
||||
data = NULL;
|
||||
*length = 0;
|
||||
}
|
||||
|
@ -228,6 +218,9 @@ static void *GetSelectionData(SDL_VideoDevice *_this, Atom selection_type, size_
|
|||
if (seln_type == XA_MIME) {
|
||||
*length = (size_t)count;
|
||||
data = CloneDataBuffer(src, length, nullterminate);
|
||||
} else if (seln_type == XA_INCR) {
|
||||
/* FIXME: Need to implement the X11 INCR protocol */
|
||||
/*SDL_Log("Need to implement the X11 INCR protocol");*/
|
||||
}
|
||||
X11_XFree(src);
|
||||
}
|
||||
|
@ -240,18 +233,17 @@ static void *GetSelectionData(SDL_VideoDevice *_this, Atom selection_type, size_
|
|||
return data;
|
||||
}
|
||||
|
||||
int X11_SetClipboardData(SDL_VideoDevice *_this, SDL_ClipboardDataCallback callback, size_t mime_count,
|
||||
const char **mime_types, void *userdata)
|
||||
int X11_SetClipboardData(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *videodata = _this->driverdata;
|
||||
Atom XA_CLIPBOARD = X11_XInternAtom(videodata->display, "CLIPBOARD", 0);
|
||||
if (XA_CLIPBOARD == None) {
|
||||
return SDL_SetError("Couldn't access X clipboard");
|
||||
}
|
||||
return SetSelectionData(_this, XA_CLIPBOARD, callback, mime_count, mime_types, userdata, SDL_FALSE);
|
||||
return SetSelectionData(_this, XA_CLIPBOARD, _this->clipboard_callback, _this->clipboard_userdata, (const char **)_this->clipboard_mime_types, _this->num_clipboard_mime_types, _this->clipboard_sequence);
|
||||
}
|
||||
|
||||
void *X11_GetClipboardData(SDL_VideoDevice *_this, size_t *length, const char *mime_type)
|
||||
void *X11_GetClipboardData(SDL_VideoDevice *_this, const char *mime_type, size_t *length)
|
||||
{
|
||||
SDL_VideoData *videodata = _this->driverdata;
|
||||
Atom XA_CLIPBOARD = X11_XInternAtom(videodata->display, "CLIPBOARD", 0);
|
||||
|
@ -260,26 +252,20 @@ void *X11_GetClipboardData(SDL_VideoDevice *_this, size_t *length, const char *m
|
|||
*length = 0;
|
||||
return NULL;
|
||||
}
|
||||
return GetSelectionData(_this, XA_CLIPBOARD, length, mime_type, SDL_FALSE);
|
||||
return GetSelectionData(_this, XA_CLIPBOARD, mime_type, length, SDL_FALSE);
|
||||
}
|
||||
|
||||
SDL_bool X11_HasClipboardData(SDL_VideoDevice *_this, const char *mime_type)
|
||||
{
|
||||
size_t length;
|
||||
void *data;
|
||||
data = X11_GetClipboardData(_this, &length, mime_type);
|
||||
data = X11_GetClipboardData(_this, mime_type, &length);
|
||||
if (data != NULL) {
|
||||
SDL_free(data);
|
||||
}
|
||||
return length > 0;
|
||||
}
|
||||
|
||||
void *X11_GetClipboardUserdata(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDLX11_ClipboardData *cb = &_this->driverdata->clipboard;
|
||||
return cb->internal ? NULL : cb->userdata;
|
||||
}
|
||||
|
||||
int X11_SetClipboardText(SDL_VideoDevice *_this, const char *text)
|
||||
{
|
||||
SDL_VideoData *videodata = _this->driverdata;
|
||||
|
@ -287,14 +273,12 @@ int X11_SetClipboardText(SDL_VideoDevice *_this, const char *text)
|
|||
if (XA_CLIPBOARD == None) {
|
||||
return SDL_SetError("Couldn't access X clipboard");
|
||||
}
|
||||
return SetSelectionData(_this, XA_CLIPBOARD, X11_ClipboardTextCallback, TEXT_MIME_TYPES_LEN, text_mime_types,
|
||||
SDL_strdup(text), SDL_TRUE);
|
||||
return SetSelectionData(_this, XA_CLIPBOARD, X11_ClipboardTextCallback, SDL_strdup(text), text_mime_types, TEXT_MIME_TYPES_LEN, 0);
|
||||
}
|
||||
|
||||
int X11_SetPrimarySelectionText(SDL_VideoDevice *_this, const char *text)
|
||||
{
|
||||
return SetSelectionData(_this, XA_PRIMARY, X11_ClipboardTextCallback, TEXT_MIME_TYPES_LEN, text_mime_types,
|
||||
SDL_strdup(text), SDL_TRUE);
|
||||
return SetSelectionData(_this, XA_PRIMARY, X11_ClipboardTextCallback, SDL_strdup(text), text_mime_types, TEXT_MIME_TYPES_LEN, 0);
|
||||
}
|
||||
|
||||
char *X11_GetClipboardText(SDL_VideoDevice *_this)
|
||||
|
@ -307,13 +291,13 @@ char *X11_GetClipboardText(SDL_VideoDevice *_this)
|
|||
return SDL_strdup("");
|
||||
}
|
||||
|
||||
return GetSelectionData(_this, XA_CLIPBOARD, &length, text_mime_types[0], SDL_TRUE);
|
||||
return GetSelectionData(_this, XA_CLIPBOARD, text_mime_types[0], &length, SDL_TRUE);
|
||||
}
|
||||
|
||||
char *X11_GetPrimarySelectionText(SDL_VideoDevice *_this)
|
||||
{
|
||||
size_t length;
|
||||
return GetSelectionData(_this, XA_PRIMARY, &length, text_mime_types[0], SDL_TRUE);
|
||||
return GetSelectionData(_this, XA_PRIMARY, text_mime_types[0], &length, SDL_TRUE);
|
||||
}
|
||||
|
||||
SDL_bool X11_HasClipboardText(SDL_VideoDevice *_this)
|
||||
|
@ -341,10 +325,10 @@ SDL_bool X11_HasPrimarySelectionText(SDL_VideoDevice *_this)
|
|||
void X11_QuitClipboard(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_VideoData *data = _this->driverdata;
|
||||
if (data->primary_selection.internal == SDL_TRUE) {
|
||||
if (data->primary_selection.sequence == 0) {
|
||||
SDL_free(data->primary_selection.userdata);
|
||||
}
|
||||
if (data->clipboard.internal == SDL_TRUE) {
|
||||
if (data->clipboard.sequence == 0) {
|
||||
SDL_free(data->clipboard.userdata);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,14 +30,12 @@ typedef struct X11_ClipboardData {
|
|||
void *userdata;
|
||||
const char **mime_types;
|
||||
size_t mime_count;
|
||||
SDL_bool internal;
|
||||
Uint32 sequence;
|
||||
} SDLX11_ClipboardData;
|
||||
|
||||
extern int X11_SetClipboardData(SDL_VideoDevice *_this, SDL_ClipboardDataCallback callback, size_t mime_count,
|
||||
const char **mime_types, void *userdata);
|
||||
extern void *X11_GetClipboardData(SDL_VideoDevice *_this, size_t *length, const char *mime_type);
|
||||
extern int X11_SetClipboardData(SDL_VideoDevice *_this);
|
||||
extern void *X11_GetClipboardData(SDL_VideoDevice *_this, const char *mime_type, size_t *length);
|
||||
extern SDL_bool X11_HasClipboardData(SDL_VideoDevice *_this, const char *mime_type);
|
||||
extern void *X11_GetClipboardUserdata(SDL_VideoDevice *_this);
|
||||
extern int X11_SetClipboardText(SDL_VideoDevice *_this, const char *text);
|
||||
extern char *X11_GetClipboardText(SDL_VideoDevice *_this);
|
||||
extern SDL_bool X11_HasClipboardText(SDL_VideoDevice *_this);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "SDL_x11touch.h"
|
||||
#include "SDL_x11xinput2.h"
|
||||
#include "SDL_x11xfixes.h"
|
||||
#include "../SDL_clipboard_c.h"
|
||||
#include "../../core/unix/SDL_poll.h"
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
|
@ -685,8 +686,9 @@ static void X11_HandleClipboardEvent(SDL_VideoDevice *_this, const XEvent *xeven
|
|||
continue;
|
||||
}
|
||||
|
||||
/* FIXME: We don't support the X11 INCR protocol for large clipboards. Do we want that? */
|
||||
seln_data = clipboard->callback(&seln_length, mime_type, clipboard->userdata);
|
||||
/* FIXME: We don't support the X11 INCR protocol for large clipboards. Do we want that? - Yes, yes we do. */
|
||||
/* This is a safe cast, XChangeProperty() doesn't take a const value, but it doesn't modify the data */
|
||||
seln_data = (unsigned char *)clipboard->callback(clipboard->userdata, mime_type, &seln_length);
|
||||
if (seln_data != NULL) {
|
||||
X11_XChangeProperty(display, req->requestor, req->property,
|
||||
req->target, 8, PropModeReplace,
|
||||
|
@ -726,13 +728,14 @@ static void X11_HandleClipboardEvent(SDL_VideoDevice *_this, const XEvent *xeven
|
|||
clipboard = &videodata->primary_selection;
|
||||
} else if (XA_CLIPBOARD != None && xevent->xselectionclear.selection == XA_CLIPBOARD) {
|
||||
clipboard = &videodata->clipboard;
|
||||
if (clipboard->internal == SDL_FALSE) {
|
||||
SDL_SendClipboardCancelled(clipboard->userdata);
|
||||
}
|
||||
}
|
||||
if (clipboard != NULL && clipboard->internal == SDL_TRUE) {
|
||||
SDL_free(clipboard->userdata);
|
||||
clipboard->userdata = NULL;
|
||||
if (clipboard && clipboard->callback) {
|
||||
if (clipboard->sequence) {
|
||||
SDL_CancelClipboardData(clipboard->sequence);
|
||||
} else {
|
||||
SDL_free(clipboard->userdata);
|
||||
}
|
||||
SDL_zerop(clipboard);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
|
|
@ -258,7 +258,6 @@ static SDL_VideoDevice *X11_CreateDevice(void)
|
|||
device->SetClipboardText = X11_SetClipboardText;
|
||||
device->GetClipboardText = X11_GetClipboardText;
|
||||
device->HasClipboardText = X11_HasClipboardText;
|
||||
device->GetClipboardUserdata = X11_GetClipboardUserdata;
|
||||
device->SetPrimarySelectionText = X11_SetPrimarySelectionText;
|
||||
device->GetPrimarySelectionText = X11_GetPrimarySelectionText;
|
||||
device->HasPrimarySelectionText = X11_HasPrimarySelectionText;
|
||||
|
|
|
@ -73,7 +73,7 @@ static int clipboard_testGetClipboardData(void *arg)
|
|||
{
|
||||
void *buffer = NULL;
|
||||
size_t length;
|
||||
buffer = SDL_GetClipboardData(&length, "image/png");
|
||||
buffer = SDL_GetClipboardData("image/png", &length);
|
||||
SDLTest_AssertPass("Call to SDL_GetClipboardData succeeded");
|
||||
|
||||
if (buffer != NULL) {
|
||||
|
@ -134,16 +134,13 @@ static int clipboard_testSetClipboardData(void *arg)
|
|||
{
|
||||
int result = -1;
|
||||
|
||||
result = SDL_SetClipboardData(NULL, 0, NULL, NULL);
|
||||
result = SDL_SetClipboardData(NULL, NULL, NULL, NULL, 0);
|
||||
SDLTest_AssertPass("Call to SDL_SetClipboardData succeeded");
|
||||
SDLTest_AssertCheck(
|
||||
result == 0,
|
||||
"Validate SDL_SetClipboardData result, expected 0, got %i",
|
||||
result);
|
||||
|
||||
SDL_GetClipboardUserdata();
|
||||
SDLTest_AssertPass("Call to SDL_GetClipboardUserdata succeeded");
|
||||
|
||||
return TEST_COMPLETED;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue