Code to get the available mime types in the clipboard
This commit is contained in:
parent
d17a6cd3a3
commit
96160b52b6
67
glfw/x11_window.c
vendored
67
glfw/x11_window.c
vendored
@ -929,6 +929,13 @@ getSelectionString(Atom selection, const char *mime_type, Atom *targets, size_t
|
||||
if (XGetSelectionOwner(_glfw.x11.display, selection) ==
|
||||
_glfw.x11.helperWindowHandle)
|
||||
{
|
||||
if (mime_type == NULL) {
|
||||
AtomArray *aa = selection == _glfw.x11.PRIMARY ? &_glfw.x11.primary_atoms : &_glfw.x11.clipboard_atoms;
|
||||
for (size_t i = 0; i < aa->sz; i++) {
|
||||
if (!write_data(object, (char*)&aa->array[i].atom, sizeof(Atom))) break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Instead of doing a large number of X round-trips just to put this
|
||||
// string into a window property and then read it back, just return it
|
||||
_GLFWClipboardData *cd = selection == _glfw.x11.PRIMARY ? &_glfw.primary : &_glfw.clipboard;
|
||||
@ -1038,6 +1045,10 @@ getSelectionString(Atom selection, const char *mime_type, Atom *targets, size_t
|
||||
} else write_data(object, data, itemCount);
|
||||
found = true;
|
||||
}
|
||||
else if (actualType == XA_ATOM && targets[i] == _glfw.x11.TARGETS) {
|
||||
found = true;
|
||||
write_data(object, data, itemCount);
|
||||
}
|
||||
|
||||
XFREE(data);
|
||||
|
||||
@ -2889,20 +2900,60 @@ void _glfwPlatformSetClipboard(GLFWClipboardType t) {
|
||||
aa->sz = 0;
|
||||
for (size_t i = 0; i < cd->num_mime_types; i++) {
|
||||
MimeAtom *a = aa->array + aa->sz++;
|
||||
if (strcmp(cd->mime_types[i], "text/plain") == 0) {
|
||||
a->atom = XA_ATOM; a->mime = "text/plain";
|
||||
a = aa->array + aa->sz++;
|
||||
a->atom = _glfw.x11.UTF8_STRING; a->mime = "text/plain";
|
||||
} else {
|
||||
*a = atom_for_mime(cd->mime_types[i]);
|
||||
}
|
||||
*a = atom_for_mime(cd->mime_types[i]);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct chunked_writer {
|
||||
char *buf; size_t sz, cap;
|
||||
} chunked_writer;
|
||||
|
||||
static bool
|
||||
write_chunk(void *object, const char *data, size_t sz) {
|
||||
chunked_writer *cw = object;
|
||||
if (cw->cap < cw->sz + sz) {
|
||||
cw->cap = MAX(cw->cap * 2, cw->sz + 8*sz);
|
||||
cw->buf = realloc(cw->buf, cw->cap);
|
||||
}
|
||||
memcpy(cw->buf + cw->sz, data, sz);
|
||||
cw->sz += sz;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
get_available_mime_types(Atom which_clipboard, GLFWclipboardwritedatafun write_data, void *object) {
|
||||
chunked_writer cw = {0};
|
||||
getSelectionString(which_clipboard, NULL, &_glfw.x11.TARGETS, 1, write_chunk, &cw);
|
||||
size_t count = 0;
|
||||
bool ok = true;
|
||||
if (cw.buf) {
|
||||
Atom *atoms = (Atom*)cw.buf;
|
||||
count = cw.sz / sizeof(Atom);
|
||||
char **names = calloc(count, sizeof(char*));
|
||||
get_atom_names(atoms, count, names);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
if (atoms[i] != _glfw.x11.UTF8_STRING && atoms[i] != XA_STRING) {
|
||||
if (ok) ok = write_data(object, names[i], strlen(names[i]));
|
||||
}
|
||||
XFree(names[i]);
|
||||
}
|
||||
free(cw.buf);
|
||||
free(names);
|
||||
}
|
||||
if (!count && ok) {
|
||||
// if no atoms then we assume text/plain is available, for compatibility with broken clients
|
||||
ok = write_data(object, "text/plain", strlen("text/plain"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
_glfwPlatformGetClipboard(GLFWClipboardType clipboard_type, const char* mime_type, GLFWclipboardwritedatafun write_data, void *object) {
|
||||
// TODO: Handle NULL mime_type
|
||||
Atom atoms[2], which = clipboard_type == GLFW_PRIMARY_SELECTION ? _glfw.x11.PRIMARY : _glfw.x11.CLIPBOARD;
|
||||
if (mime_type == NULL) {
|
||||
get_available_mime_types(which, write_data, object);
|
||||
return;
|
||||
}
|
||||
size_t count = 1;
|
||||
if (strcmp(mime_type, "text/plain") == 0) {
|
||||
atoms[0] = _glfw.x11.UTF8_STRING;
|
||||
|
||||
@ -2,10 +2,13 @@
|
||||
# License: GPLv3 Copyright: 2022, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
import io
|
||||
from typing import IO, Callable, Dict, Union, List
|
||||
from typing import IO, Callable, Dict, List, Tuple, Union
|
||||
|
||||
from .conf.utils import uniq
|
||||
from .constants import supports_primary_selection
|
||||
from .fast_data_types import GLFW_CLIPBOARD, get_boss, set_clipboard_data_types, get_clipboard_mime
|
||||
from .fast_data_types import (
|
||||
GLFW_CLIPBOARD, get_boss, get_clipboard_mime, set_clipboard_data_types
|
||||
)
|
||||
|
||||
DataType = Union[bytes, 'IO[bytes]']
|
||||
|
||||
@ -31,7 +34,15 @@ class Clipboard:
|
||||
return b''.join(parts).decode('utf-8', 'replace')
|
||||
|
||||
def get_mime(self, mime: str, output: Callable[[bytes], None]) -> None:
|
||||
get_clipboard_mime(self.clipboard_type, mime, output)
|
||||
if self.enabled:
|
||||
get_clipboard_mime(self.clipboard_type, mime, output)
|
||||
|
||||
def get_available_mime_types_for_paste(self) -> Tuple[str, ...]:
|
||||
if self.enabled:
|
||||
parts: List[bytes] = []
|
||||
get_clipboard_mime(self.clipboard_type, None, parts.append)
|
||||
return tuple(x.decode('utf-8', 'replace') for x in uniq(parts))
|
||||
return ()
|
||||
|
||||
def __call__(self, mime: str) -> Callable[[], bytes]:
|
||||
data = self.data.get(mime, b'')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user