Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
GH Action committed Sep 17, 2024
1 parent baeac83 commit b499b4f
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 1 deletion.
1 change: 1 addition & 0 deletions sokol/app/app.odin
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ Log_Item :: enum i32 {
LINUX_X11_OPEN_DISPLAY_FAILED,
LINUX_X11_QUERY_SYSTEM_DPI_FAILED,
LINUX_X11_DROPPED_FILE_URI_WRONG_SCHEME,
LINUX_X11_FAILED_TO_BECOME_OWNER_OF_CLIPBOARD,
ANDROID_UNSUPPORTED_INPUT_EVENT_INPUT_CB,
ANDROID_UNSUPPORTED_INPUT_EVENT_MAIN_CB,
ANDROID_READ_MSG_FAILED,
Expand Down
126 changes: 125 additions & 1 deletion sokol/c/sokol_app.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
screen keyboard | --- | --- | --- | YES | TODO | YES
swap interval | YES | YES | YES | YES | TODO | YES
high-dpi | YES | YES | TODO | YES | YES | YES
clipboard | YES | YES | TODO | --- | --- | YES
clipboard | YES | YES | YES | --- | --- | YES
MSAA | YES | YES | YES | YES | YES | YES
drag'n'drop | YES | YES | YES | --- | --- | YES
window icon | YES | YES(1)| YES | --- | --- | YES
Expand Down Expand Up @@ -1603,6 +1603,7 @@ typedef struct sapp_allocator {
_SAPP_LOGITEM_XMACRO(LINUX_X11_OPEN_DISPLAY_FAILED, "XOpenDisplay() failed") \
_SAPP_LOGITEM_XMACRO(LINUX_X11_QUERY_SYSTEM_DPI_FAILED, "failed to query system dpi value, assuming default 96.0") \
_SAPP_LOGITEM_XMACRO(LINUX_X11_DROPPED_FILE_URI_WRONG_SCHEME, "dropped file URL doesn't start with 'file://'") \
_SAPP_LOGITEM_XMACRO(LINUX_X11_FAILED_TO_BECOME_OWNER_OF_CLIPBOARD, "X11: Failed to become owner of clipboard selection") \
_SAPP_LOGITEM_XMACRO(ANDROID_UNSUPPORTED_INPUT_EVENT_INPUT_CB, "unsupported input event encountered in _sapp_android_input_cb()") \
_SAPP_LOGITEM_XMACRO(ANDROID_UNSUPPORTED_INPUT_EVENT_MAIN_CB, "unsupported input event encountered in _sapp_android_main_cb()") \
_SAPP_LOGITEM_XMACRO(ANDROID_READ_MSG_FAILED, "failed to read message in _sapp_android_main_cb()") \
Expand Down Expand Up @@ -2162,6 +2163,7 @@ inline void sapp_run(const sapp_desc& desc) { return sapp_run(&desc); }
#include <limits.h> /* LONG_MAX */
#include <pthread.h> /* only used a linker-guard, search for _sapp_linux_run() and see first comment */
#include <time.h>
#include <poll.h>
#endif

#if defined(_SAPP_APPLE)
Expand Down Expand Up @@ -2752,6 +2754,8 @@ typedef struct {
float dpi;
unsigned char error_code;
Atom UTF8_STRING;
Atom CLIPBOARD;
Atom TARGETS;
Atom WM_PROTOCOLS;
Atom WM_DELETE_WINDOW;
Atom WM_STATE;
Expand Down Expand Up @@ -9618,6 +9622,8 @@ _SOKOL_PRIVATE void _sapp_x11_init_extensions(void) {
_sapp.x11.NET_WM_ICON = XInternAtom(_sapp.x11.display, "_NET_WM_ICON", False);
_sapp.x11.NET_WM_STATE = XInternAtom(_sapp.x11.display, "_NET_WM_STATE", False);
_sapp.x11.NET_WM_STATE_FULLSCREEN = XInternAtom(_sapp.x11.display, "_NET_WM_STATE_FULLSCREEN", False);
_sapp.x11.CLIPBOARD = XInternAtom(_sapp.x11.display, "CLIPBOARD", False);
_sapp.x11.TARGETS = XInternAtom(_sapp.x11.display, "TARGETS", False);
if (_sapp.drop.enabled) {
_sapp.x11.xdnd.XdndAware = XInternAtom(_sapp.x11.display, "XdndAware", False);
_sapp.x11.xdnd.XdndEnter = XInternAtom(_sapp.x11.display, "XdndEnter", False);
Expand Down Expand Up @@ -10463,6 +10469,75 @@ _SOKOL_PRIVATE void _sapp_x11_lock_mouse(bool lock) {
XFlush(_sapp.x11.display);
}

_SOKOL_PRIVATE void _sapp_x11_set_clipboard_string(const char* str) {
SOKOL_ASSERT(_sapp.clipboard.enabled && _sapp.clipboard.buffer);
if (strlen(str) >= (size_t)_sapp.clipboard.buf_size) {
_SAPP_ERROR(CLIPBOARD_STRING_TOO_BIG);
}
XSetSelectionOwner(_sapp.x11.display, _sapp.x11.CLIPBOARD, _sapp.x11.window, CurrentTime);
if (XGetSelectionOwner(_sapp.x11.display, _sapp.x11.CLIPBOARD) != _sapp.x11.window) {
_SAPP_ERROR(LINUX_X11_FAILED_TO_BECOME_OWNER_OF_CLIPBOARD);
}
}

_SOKOL_PRIVATE const char* _sapp_x11_get_clipboard_string(void) {
SOKOL_ASSERT(_sapp.clipboard.enabled && _sapp.clipboard.buffer);
Atom none = XInternAtom(_sapp.x11.display, "SAPP_SELECTION", False);
Atom incremental = XInternAtom(_sapp.x11.display, "INCR", False);
if (XGetSelectionOwner(_sapp.x11.display, _sapp.x11.CLIPBOARD) == _sapp.x11.window) {
// 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
return _sapp.clipboard.buffer;
}
XConvertSelection(_sapp.x11.display,
_sapp.x11.CLIPBOARD,
_sapp.x11.UTF8_STRING,
none,
_sapp.x11.window,
CurrentTime);
XEvent event;
while (!XCheckTypedWindowEvent(_sapp.x11.display, _sapp.x11.window, SelectionNotify, &event)) {
// Wait for event data to arrive on the X11 display socket
struct pollfd fd = { ConnectionNumber(_sapp.x11.display), POLLIN };
while (!XPending(_sapp.x11.display)) {
poll(&fd, 1, -1);
}
}
if (event.xselection.property == None) {
return NULL;
}
char* data = NULL;
Atom actualType;
int actualFormat;
unsigned long itemCount, bytesAfter;
const bool ret = XGetWindowProperty(_sapp.x11.display,
event.xselection.requestor,
event.xselection.property,
0,
LONG_MAX,
True,
_sapp.x11.UTF8_STRING,
&actualType,
&actualFormat,
&itemCount,
&bytesAfter,
(unsigned char**) &data);
if (ret != Success || data == NULL) {
if (data != NULL) {
XFree(data);
}
return NULL;
}
if ((actualType == incremental) || (itemCount >= (size_t)_sapp.clipboard.buf_size)) {
_SAPP_ERROR(CLIPBOARD_STRING_TOO_BIG);
XFree(data);
return NULL;
}
_sapp_strcpy(data, _sapp.clipboard.buffer, _sapp.clipboard.buf_size);
XFree(data);
return _sapp.clipboard.buffer;
}

_SOKOL_PRIVATE void _sapp_x11_update_window_title(void) {
Xutf8SetWMProperties(_sapp.x11.display,
_sapp.x11.window,
Expand Down Expand Up @@ -11202,6 +11277,48 @@ _SOKOL_PRIVATE void _sapp_x11_on_clientmessage(XEvent* event) {
}
}

_SOKOL_PRIVATE void _sapp_x11_on_selectionrequest(XEvent* event) {
XSelectionRequestEvent* req = &event->xselectionrequest;
if (req->selection != _sapp.x11.CLIPBOARD) {
return;
}
if (!_sapp.clipboard.enabled) {
return;
}
SOKOL_ASSERT(_sapp.clipboard.buffer);
XSelectionEvent reply;
_sapp_clear(&reply, sizeof(reply));
reply.type = SelectionNotify;
reply.display = req->display;
reply.requestor = req->requestor;
reply.selection = req->selection;
reply.target = req->target;
reply.property = req->property;
reply.time = req->time;
if (req->target == _sapp.x11.UTF8_STRING) {
XChangeProperty(_sapp.x11.display,
req->requestor,
req->property,
_sapp.x11.UTF8_STRING,
8,
PropModeReplace,
(unsigned char*) _sapp.clipboard.buffer,
strlen(_sapp.clipboard.buffer));
} else if (req->target == _sapp.x11.TARGETS) {
XChangeProperty(_sapp.x11.display,
req->requestor,
req->property,
XA_ATOM,
32,
PropModeReplace,
(unsigned char*) &_sapp.x11.UTF8_STRING,
1);
} else {
reply.property = None;
}
XSendEvent(_sapp.x11.display, req->requestor, False, 0, (XEvent*) &reply);
}

_SOKOL_PRIVATE void _sapp_x11_process_event(XEvent* event) {
switch (event->type) {
case GenericEvent:
Expand Down Expand Up @@ -11243,6 +11360,9 @@ _SOKOL_PRIVATE void _sapp_x11_process_event(XEvent* event) {
case SelectionNotify:
_sapp_x11_on_selectionnotify(event);
break;
case SelectionRequest:
_sapp_x11_on_selectionrequest(event);
break;
case DestroyNotify:
// not a bug
break;
Expand Down Expand Up @@ -11723,6 +11843,8 @@ SOKOL_API_IMPL void sapp_set_clipboard_string(const char* str) {
_sapp_emsc_set_clipboard_string(str);
#elif defined(_SAPP_WIN32)
_sapp_win32_set_clipboard_string(str);
#elif defined(_SAPP_LINUX)
_sapp_x11_set_clipboard_string(str);
#else
/* not implemented */
#endif
Expand All @@ -11739,6 +11861,8 @@ SOKOL_API_IMPL const char* sapp_get_clipboard_string(void) {
return _sapp.clipboard.buffer;
#elif defined(_SAPP_WIN32)
return _sapp_win32_get_clipboard_string();
#elif defined(_SAPP_LINUX)
return _sapp_x11_get_clipboard_string();
#else
/* not implemented */
return _sapp.clipboard.buffer;
Expand Down

0 comments on commit b499b4f

Please sign in to comment.