mirror of https://github.com/encounter/SDL.git
Added in a MIME-type to the X11 clipboard. (#4385)
This commit is contained in:
parent
5346cf842c
commit
a203194893
|
@ -27,14 +27,7 @@
|
||||||
#include "SDL_events.h"
|
#include "SDL_events.h"
|
||||||
#include "SDL_x11video.h"
|
#include "SDL_x11video.h"
|
||||||
#include "SDL_timer.h"
|
#include "SDL_timer.h"
|
||||||
|
#include "SDL_x11clipboard.h"
|
||||||
|
|
||||||
/* If you don't support UTF-8, you might use XA_STRING here */
|
|
||||||
#ifdef X_HAVE_UTF8_STRING
|
|
||||||
#define TEXT_FORMAT X11_XInternAtom(display, "UTF8_STRING", False)
|
|
||||||
#else
|
|
||||||
#define TEXT_FORMAT XA_STRING
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Get any application owned window handle for clipboard association */
|
/* Get any application owned window handle for clipboard association */
|
||||||
static Window
|
static Window
|
||||||
|
@ -59,19 +52,77 @@ GetWindow(_THIS)
|
||||||
return data->clipboard_window;
|
return data->clipboard_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* We use our own cut-buffer for intermediate storage instead of
|
/* We use our own cut-buffer for intermediate storage instead of
|
||||||
XA_CUT_BUFFER0 because their use isn't really defined for holding UTF8. */
|
XA_CUT_BUFFER0 because their use isn't really defined for holding UTF8. */
|
||||||
Atom
|
Atom
|
||||||
X11_GetSDLCutBufferClipboardType(Display *display)
|
X11_GetSDLCutBufferClipboardType(Display *display, enum ESDLX11ClipboardMimeType mime_type)
|
||||||
{
|
{
|
||||||
return X11_XInternAtom(display, "SDL_CUTBUFFER", False);
|
switch (mime_type) {
|
||||||
|
case SDL_X11_CLIPBOARD_MIME_TYPE_STRING:
|
||||||
|
case SDL_X11_CLIPBOARD_MIME_TYPE_TEXT_PLAIN:
|
||||||
|
#ifdef X_HAVE_UTF8_STRING
|
||||||
|
case SDL_X11_CLIPBOARD_MIME_TYPE_TEXT_PLAIN_UTF8:
|
||||||
|
#endif
|
||||||
|
case SDL_X11_CLIPBOARD_MIME_TYPE_TEXT:
|
||||||
|
return X11_XInternAtom(display, "SDL_CUTBUFFER", False);
|
||||||
|
default:
|
||||||
|
SDL_SetError("Can't find mime_type.");
|
||||||
|
return XA_STRING;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Atom
|
||||||
|
X11_GetSDLCutBufferClipboardExternalFormat(Display *display, enum ESDLX11ClipboardMimeType mime_type)
|
||||||
|
{
|
||||||
|
switch (mime_type) {
|
||||||
|
case SDL_X11_CLIPBOARD_MIME_TYPE_STRING:
|
||||||
|
/* If you don't support UTF-8, you might use XA_STRING here */
|
||||||
|
#ifdef X_HAVE_UTF8_STRING
|
||||||
|
return X11_XInternAtom(display, "UTF8_STRING", False);
|
||||||
|
#else
|
||||||
|
return XA_STRING;
|
||||||
|
#endif
|
||||||
|
case SDL_X11_CLIPBOARD_MIME_TYPE_TEXT_PLAIN:
|
||||||
|
return X11_XInternAtom(display, "text/plain", False);
|
||||||
|
#ifdef X_HAVE_UTF8_STRING
|
||||||
|
case SDL_X11_CLIPBOARD_MIME_TYPE_TEXT_PLAIN_UTF8:
|
||||||
|
return X11_XInternAtom(display, "text/plain;charset=utf-8", False);
|
||||||
|
#endif
|
||||||
|
case SDL_X11_CLIPBOARD_MIME_TYPE_TEXT:
|
||||||
|
return X11_XInternAtom(display, "TEXT", False);
|
||||||
|
default:
|
||||||
|
SDL_SetError("Can't find mime_type.");
|
||||||
|
return XA_STRING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Atom
|
||||||
|
X11_GetSDLCutBufferClipboardInternalFormat(Display *display, enum ESDLX11ClipboardMimeType mime_type)
|
||||||
|
{
|
||||||
|
switch (mime_type) {
|
||||||
|
case SDL_X11_CLIPBOARD_MIME_TYPE_STRING:
|
||||||
|
case SDL_X11_CLIPBOARD_MIME_TYPE_TEXT_PLAIN:
|
||||||
|
#ifdef X_HAVE_UTF8_STRING
|
||||||
|
case SDL_X11_CLIPBOARD_MIME_TYPE_TEXT_PLAIN_UTF8:
|
||||||
|
#endif
|
||||||
|
case SDL_X11_CLIPBOARD_MIME_TYPE_TEXT:
|
||||||
|
/* If you don't support UTF-8, you might use XA_STRING here */
|
||||||
|
#ifdef X_HAVE_UTF8_STRING
|
||||||
|
return X11_XInternAtom(display, "UTF8_STRING", False);
|
||||||
|
#else
|
||||||
|
return XA_STRING;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
SDL_SetError("Can't find mime_type.");
|
||||||
|
return XA_STRING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
X11_SetClipboardText(_THIS, const char *text)
|
X11_SetClipboardText(_THIS, const char *text)
|
||||||
{
|
{
|
||||||
Display *display = ((SDL_VideoData *) _this->driverdata)->display;
|
Display *display = ((SDL_VideoData *) _this->driverdata)->display;
|
||||||
Atom format;
|
|
||||||
Window window;
|
Window window;
|
||||||
Atom XA_CLIPBOARD = X11_XInternAtom(display, "CLIPBOARD", 0);
|
Atom XA_CLIPBOARD = X11_XInternAtom(display, "CLIPBOARD", 0);
|
||||||
|
|
||||||
|
@ -82,9 +133,8 @@ X11_SetClipboardText(_THIS, const char *text)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the selection on the root window */
|
/* Save the selection on the root window */
|
||||||
format = TEXT_FORMAT;
|
|
||||||
X11_XChangeProperty(display, DefaultRootWindow(display),
|
X11_XChangeProperty(display, DefaultRootWindow(display),
|
||||||
X11_GetSDLCutBufferClipboardType(display), format, 8, PropModeReplace,
|
X11_GetSDLCutBufferClipboardType(display, SDL_X11_CLIPBOARD_MIME_TYPE_STRING), X11_GetSDLCutBufferClipboardInternalFormat(display, SDL_X11_CLIPBOARD_MIME_TYPE_STRING), 8, PropModeReplace,
|
||||||
(const unsigned char *)text, SDL_strlen(text));
|
(const unsigned char *)text, SDL_strlen(text));
|
||||||
|
|
||||||
if (XA_CLIPBOARD != None &&
|
if (XA_CLIPBOARD != None &&
|
||||||
|
@ -125,7 +175,7 @@ X11_GetClipboardText(_THIS)
|
||||||
|
|
||||||
/* Get the window that holds the selection */
|
/* Get the window that holds the selection */
|
||||||
window = GetWindow(_this);
|
window = GetWindow(_this);
|
||||||
format = TEXT_FORMAT;
|
format = X11_GetSDLCutBufferClipboardInternalFormat(display, SDL_X11_CLIPBOARD_MIME_TYPE_STRING);
|
||||||
owner = X11_XGetSelectionOwner(display, XA_CLIPBOARD);
|
owner = X11_XGetSelectionOwner(display, XA_CLIPBOARD);
|
||||||
if (owner == None) {
|
if (owner == None) {
|
||||||
/* Fall back to ancient X10 cut-buffers which do not support UTF8 strings*/
|
/* Fall back to ancient X10 cut-buffers which do not support UTF8 strings*/
|
||||||
|
@ -134,7 +184,7 @@ X11_GetClipboardText(_THIS)
|
||||||
format = XA_STRING;
|
format = XA_STRING;
|
||||||
} else if (owner == window) {
|
} else if (owner == window) {
|
||||||
owner = DefaultRootWindow(display);
|
owner = DefaultRootWindow(display);
|
||||||
selection = X11_GetSDLCutBufferClipboardType(display);
|
selection = X11_GetSDLCutBufferClipboardType(display, SDL_X11_CLIPBOARD_MIME_TYPE_STRING);
|
||||||
} else {
|
} else {
|
||||||
/* Request that the selection owner copy the data to our window */
|
/* Request that the selection owner copy the data to our window */
|
||||||
owner = window;
|
owner = window;
|
||||||
|
|
|
@ -23,10 +23,22 @@
|
||||||
#ifndef SDL_x11clipboard_h_
|
#ifndef SDL_x11clipboard_h_
|
||||||
#define SDL_x11clipboard_h_
|
#define SDL_x11clipboard_h_
|
||||||
|
|
||||||
|
enum ESDLX11ClipboardMimeType {
|
||||||
|
SDL_X11_CLIPBOARD_MIME_TYPE_STRING,
|
||||||
|
SDL_X11_CLIPBOARD_MIME_TYPE_TEXT_PLAIN,
|
||||||
|
#ifdef X_HAVE_UTF8_STRING
|
||||||
|
SDL_X11_CLIPBOARD_MIME_TYPE_TEXT_PLAIN_UTF8,
|
||||||
|
#endif
|
||||||
|
SDL_X11_CLIPBOARD_MIME_TYPE_TEXT,
|
||||||
|
SDL_X11_CLIPBOARD_MIME_TYPE_MAX
|
||||||
|
};
|
||||||
|
|
||||||
extern int X11_SetClipboardText(_THIS, const char *text);
|
extern int X11_SetClipboardText(_THIS, const char *text);
|
||||||
extern char *X11_GetClipboardText(_THIS);
|
extern char *X11_GetClipboardText(_THIS);
|
||||||
extern SDL_bool X11_HasClipboardText(_THIS);
|
extern SDL_bool X11_HasClipboardText(_THIS);
|
||||||
extern Atom X11_GetSDLCutBufferClipboardType(Display *display);
|
extern Atom X11_GetSDLCutBufferClipboardType(Display *display, enum ESDLX11ClipboardMimeType mime_type);
|
||||||
|
extern Atom X11_GetSDLCutBufferClipboardExternalFormat(Display *display, enum ESDLX11ClipboardMimeType mime_type);
|
||||||
|
extern Atom X11_GetSDLCutBufferClipboardInternalFormat(Display *display, enum ESDLX11ClipboardMimeType mime_type);
|
||||||
|
|
||||||
#endif /* SDL_x11clipboard_h_ */
|
#endif /* SDL_x11clipboard_h_ */
|
||||||
|
|
||||||
|
|
|
@ -562,6 +562,7 @@ X11_UpdateUserTime(SDL_WindowData *data, const unsigned long latest)
|
||||||
static void
|
static void
|
||||||
X11_HandleClipboardEvent(_THIS, const XEvent *xevent)
|
X11_HandleClipboardEvent(_THIS, const XEvent *xevent)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
|
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
|
||||||
Display *display = videodata->display;
|
Display *display = videodata->display;
|
||||||
|
|
||||||
|
@ -573,10 +574,12 @@ X11_HandleClipboardEvent(_THIS, const XEvent *xevent)
|
||||||
case SelectionRequest: {
|
case SelectionRequest: {
|
||||||
const XSelectionRequestEvent *req = &xevent->xselectionrequest;
|
const XSelectionRequestEvent *req = &xevent->xselectionrequest;
|
||||||
XEvent sevent;
|
XEvent sevent;
|
||||||
int seln_format;
|
int seln_format, mime_formats;
|
||||||
unsigned long nbytes;
|
unsigned long nbytes;
|
||||||
unsigned long overflow;
|
unsigned long overflow;
|
||||||
unsigned char *seln_data;
|
unsigned char *seln_data;
|
||||||
|
Atom supportedFormats[SDL_X11_CLIPBOARD_MIME_TYPE_MAX+1];
|
||||||
|
Atom XA_TARGETS = X11_XInternAtom(display, "TARGETS", 0);
|
||||||
|
|
||||||
#ifdef DEBUG_XEVENTS
|
#ifdef DEBUG_XEVENTS
|
||||||
printf("window CLIPBOARD: SelectionRequest (requestor = %ld, target = %ld)\n",
|
printf("window CLIPBOARD: SelectionRequest (requestor = %ld, target = %ld)\n",
|
||||||
|
@ -594,27 +597,38 @@ X11_HandleClipboardEvent(_THIS, const XEvent *xevent)
|
||||||
/* !!! FIXME: We were probably storing this on the root window
|
/* !!! FIXME: We were probably storing this on the root window
|
||||||
because an SDL window might go away...? but we don't have to do
|
because an SDL window might go away...? but we don't have to do
|
||||||
this now (or ever, really). */
|
this now (or ever, really). */
|
||||||
if (X11_XGetWindowProperty(display, DefaultRootWindow(display),
|
|
||||||
X11_GetSDLCutBufferClipboardType(display), 0, INT_MAX/4, False, req->target,
|
if (req->target == XA_TARGETS) {
|
||||||
&sevent.xselection.target, &seln_format, &nbytes,
|
supportedFormats[0] = XA_TARGETS;
|
||||||
&overflow, &seln_data) == Success) {
|
mime_formats = 1;
|
||||||
/* !!! FIXME: cache atoms */
|
for (i = 0; i < SDL_X11_CLIPBOARD_MIME_TYPE_MAX; ++i)
|
||||||
Atom XA_TARGETS = X11_XInternAtom(display, "TARGETS", 0);
|
supportedFormats[mime_formats++] = X11_GetSDLCutBufferClipboardExternalFormat(display, i);
|
||||||
if (sevent.xselection.target == req->target) {
|
X11_XChangeProperty(display, req->requestor, req->property,
|
||||||
X11_XChangeProperty(display, req->requestor, req->property,
|
XA_ATOM, 32, PropModeReplace,
|
||||||
sevent.xselection.target, seln_format, PropModeReplace,
|
(unsigned char*)supportedFormats,
|
||||||
seln_data, nbytes);
|
mime_formats);
|
||||||
sevent.xselection.property = req->property;
|
sevent.xselection.property = req->property;
|
||||||
} else if (XA_TARGETS == req->target) {
|
sevent.xselection.target = XA_TARGETS;
|
||||||
Atom SupportedFormats[] = { XA_TARGETS, sevent.xselection.target };
|
} else {
|
||||||
X11_XChangeProperty(display, req->requestor, req->property,
|
for (i = 0; i < SDL_X11_CLIPBOARD_MIME_TYPE_MAX; ++i) {
|
||||||
XA_ATOM, 32, PropModeReplace,
|
if (X11_GetSDLCutBufferClipboardExternalFormat(display, i) != req->target)
|
||||||
(unsigned char*)SupportedFormats,
|
continue;
|
||||||
SDL_arraysize(SupportedFormats));
|
if (X11_XGetWindowProperty(display, DefaultRootWindow(display),
|
||||||
sevent.xselection.property = req->property;
|
X11_GetSDLCutBufferClipboardType(display, i), 0, INT_MAX/4, False, X11_GetSDLCutBufferClipboardInternalFormat(display, i),
|
||||||
sevent.xselection.target = XA_TARGETS;
|
&sevent.xselection.target, &seln_format, &nbytes,
|
||||||
|
&overflow, &seln_data) == Success) {
|
||||||
|
if (seln_format != None) {
|
||||||
|
X11_XChangeProperty(display, req->requestor, req->property,
|
||||||
|
sevent.xselection.target, seln_format, PropModeReplace,
|
||||||
|
seln_data, nbytes);
|
||||||
|
sevent.xselection.property = req->property;
|
||||||
|
X11_XFree(seln_data);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
X11_XFree(seln_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
X11_XFree(seln_data);
|
|
||||||
}
|
}
|
||||||
X11_XSendEvent(display, req->requestor, False, 0, &sevent);
|
X11_XSendEvent(display, req->requestor, False, 0, &sevent);
|
||||||
X11_XSync(display, False);
|
X11_XSync(display, False);
|
||||||
|
|
Loading…
Reference in New Issue