aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/window/window.c75
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;
+ }
}
}
}