diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/window/window.c | 75 |
1 files changed, 52 insertions, 23 deletions
diff --git a/src/window/window.c b/src/window/window.c index 285b255..b60c9e4 100644 --- a/src/window/window.c +++ b/src/window/window.c @@ -952,19 +952,20 @@ bool mgl_window_get_clipboard(mgl_window *self, mgl_clipboard_callback callback, if(!xev.xselection.property || !xev.xselection.target || xev.xselection.selection != x11_context->clipboard_atom) continue; - Atom type; + Atom type = None; int format; unsigned long items; unsigned long remaining_bytes = 32768; unsigned char *data = NULL; if(xev.xselection.target == XA_TARGETS && requested_clipboard_type == None) { - if(XGetWindowProperty(context->connection, self->window, x11_context->clipboard_atom, 0, 1024, False, AnyPropertyType, &type, &format, &items, &remaining_bytes, &data) == Success && data) { + 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; 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; } else { XConvertSelection(context->connection, x11_context->clipboard_atom, requested_clipboard_type, x11_context->clipboard_atom, self->window, CurrentTime); @@ -973,34 +974,62 @@ bool mgl_window_get_clipboard(mgl_window *self, mgl_clipboard_callback callback, XFree(data); } } else if(xev.xselection.target == requested_clipboard_type) { - bool success = true; - unsigned long offset = 0; - - /* offset is specified in XGetWindowProperty as a multiple of 32-bit (4 bytes) */ - while(XGetWindowProperty(context->connection, self->window, x11_context->clipboard_atom, offset/4, 32768, False, AnyPropertyType, &type, &format, &items, &remaining_bytes, &data) == Success && data) { - const mgl_clipboard_type clipboard_type = atom_type_to_supported_clipboard_type(x11_context, type, format); - if(type != x11_context->incr_atom && clipboard_type != -1) { - if(!callback(data, items, clipboard_type, userdata)) { - success = false; + unsigned int total_size = 0; + unsigned int total_offset = 0; + 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) { + if(mgl_clock_get_elapsed_time_seconds(&timeout_timer) >= timeout_seconds) break; + + if(type == x11_context->incr_atom) { + XDeleteProperty(context->connection, self->window, x11_context->incr_atom); + /* TODO: */ + /*receive_property_notify_event(self);*/ + total_size = *(unsigned long*)data; + offset = 0; + type = None; + XFree(data); + data = NULL; + continue; } - } - offset += (items * (format/8)); // format is the bit size of the data - XFree(data); - if(remaining_bytes == 0) - break; + 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)) { + XFree(data); + break; + } + } + offset += num_items_bytes; // format is the bit size of the data + total_offset += num_items_bytes; - if(mgl_clock_get_elapsed_time_seconds(&timeout_timer) >= timeout_seconds) { - success = false; - break; + if(data) { + XFree(data); + data = NULL; + } + + if((total_size == 0 && remaining_bytes == 0) || (total_size > 0 && total_offset >= total_size)) { + success = true; + break; + } + + if(remaining_bytes == 0) + break; } - } - if(remaining_bytes != 0) - success = false; + 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; + } - return success; + return success; + } } } } |