From af1a278867f879f74a676fb3c07a34d2c0e60791 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 18 Dec 2022 02:12:59 +0100 Subject: Attempt to do clipboard get property for large data (incr). Should fix clipboard image pasting on wayland --- src/window/window.c | 87 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/window/window.c b/src/window/window.c index 60f6277..481d17a 100644 --- a/src/window/window.c +++ b/src/window/window.c @@ -1095,12 +1095,17 @@ bool mgl_window_get_clipboard(mgl_window *self, mgl_clipboard_callback callback, mgl_clock timeout_timer; mgl_clock_init(&timeout_timer); + bool success = false; const double timeout_seconds = 5.0; while(mgl_clock_get_elapsed_time_seconds(&timeout_timer) < timeout_seconds) { + /* TODO: Wait for SelectionNotify event instead */ while(XCheckTypedWindowEvent(context->connection, self->window, SelectionNotify, &xev)) { + if(mgl_clock_get_elapsed_time_seconds(&timeout_timer) >= timeout_seconds) + break; + if(!xev.xselection.property) - return false; + continue; if(!xev.xselection.target || xev.xselection.selection != x11_context->clipboard_atom) continue; @@ -1108,87 +1113,99 @@ bool mgl_window_get_clipboard(mgl_window *self, mgl_clipboard_callback callback, Atom type = None; int format; unsigned long items; - unsigned long remaining_bytes = 32768; + unsigned long remaining_bytes = 0; unsigned char *data = NULL; if(xev.xselection.target == XA_TARGETS && requested_clipboard_type == None) { - if(XGetWindowProperty(context->connection, xev.xselection.requestor, xev.xselection.property, 0, 1024, False, AnyPropertyType, &type, &format, &items, &remaining_bytes, &data) == Success && data) { - bool got_clipboard = false; + /* TODO: Wait for PropertyNotify event instead */ + if(XGetWindowProperty(context->connection, xev.xselection.requestor, xev.xselection.property, 0, 1024, False, PropertyNewValue, &type, &format, &items, &remaining_bytes, &data) == Success && data) { if(type != x11_context->incr_atom && type == XA_ATOM && format == 32) { requested_clipboard_type = find_matching_atom(supported_clipboard_types, num_supported_clipboard_types, (Atom*)data, items); if(requested_clipboard_type == None) { /* Pasting clipboard data type we dont support */ XFree(data); - return false; + goto done; } else { XConvertSelection(context->connection, x11_context->clipboard_atom, requested_clipboard_type, x11_context->clipboard_atom, self->window, CurrentTime); } } + XFree(data); } } else if(xev.xselection.target == requested_clipboard_type) { - unsigned int total_size = 0; - unsigned int total_offset = 0; + bool got_data = false; + long chunk_size = 65536; + + //XDeleteProperty(context->connection, self->window, x11_context->incr_atom); + //XFlush(context->connection); + while(mgl_clock_get_elapsed_time_seconds(&timeout_timer) < timeout_seconds) { - bool success = false; unsigned long offset = 0; /* offset is specified in XGetWindowProperty as a multiple of 32-bit (4 bytes) */ - while(XGetWindowProperty(context->connection, xev.xselection.requestor, xev.xselection.property, offset/4, 32768, True, AnyPropertyType, &type, &format, &items, &remaining_bytes, &data) == Success) { + /* TODO: Wait for PropertyNotify event instead */ + while(XGetWindowProperty(context->connection, xev.xselection.requestor, xev.xselection.property, offset/4, chunk_size, True, PropertyNewValue, &type, &format, &items, &remaining_bytes, &data) == Success) { if(mgl_clock_get_elapsed_time_seconds(&timeout_timer) >= timeout_seconds) break; if(type == x11_context->incr_atom) { + if(data) + chunk_size = *(long*)data; XDeleteProperty(context->connection, self->window, x11_context->incr_atom); - /* TODO: */ - /*receive_property_notify_event(self);*/ - total_size = *(unsigned long*)data; - offset = 0; - type = None; + XFlush(context->connection); XFree(data); data = NULL; - continue; + break; + } else if(type == requested_clipboard_type) { + got_data = true; } - const size_t num_items_bytes = items * (format/8); - const mgl_clipboard_type clipboard_type = atom_type_to_supported_clipboard_type(x11_context, type, format); - if(data && num_items_bytes > 0 && clipboard_type != -1) { - if(!callback(data, num_items_bytes, clipboard_type, userdata)) { + if(!got_data && items == 0) { + XDeleteProperty(context->connection, self->window, type); + XFlush(context->connection); + if(data) { XFree(data); - break; + data = NULL; + } + break; + } + + const size_t num_items_bytes = items * (format/8); /* format is the bit size of the data */ + if(got_data) { + const mgl_clipboard_type clipboard_type = atom_type_to_supported_clipboard_type(x11_context, type, format); + if(data && num_items_bytes > 0 && clipboard_type != -1) { + if(!callback(data, num_items_bytes, clipboard_type, userdata)) { + XFree(data); + goto done; + } } } - offset += num_items_bytes; // format is the bit size of the data - total_offset += num_items_bytes; + offset += num_items_bytes; if(data) { XFree(data); data = NULL; } - if((total_size == 0 && remaining_bytes == 0) || (total_size > 0 && total_offset >= total_size)) { + if(got_data && num_items_bytes == 0/* && format == 8*/) { success = true; - break; + goto done; } if(remaining_bytes == 0) - break; - } - - if((total_size == 0 && remaining_bytes != 0) || (total_size > 0 && total_offset < total_size)) { - offset = 0; - XDeleteProperty(context->connection, self->window, x11_context->incr_atom); - continue; + break; } - - return success; } + + goto done; } } } - /* Timed out waiting for clipboard */ - return false; + done: + if(requested_clipboard_type) + XDeleteProperty(context->connection, self->window, requested_clipboard_type); + return success; } typedef struct { -- cgit v1.2.3