diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c index 8a35a0bd3cd..ec7d5ab1417 100644 --- a/dlls/winex11.drv/clipboard.c +++ b/dlls/winex11.drv/clipboard.c @@ -325,7 +325,7 @@ static Window thread_selection_wnd(void) XSetWindowAttributes attr; attr.event_mask = (ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | - ButtonPressMask | ButtonReleaseMask | EnterWindowMask); + ButtonPressMask | ButtonReleaseMask | EnterWindowMask | PropertyChangeMask); wine_tsx11_lock(); w = XCreateWindow(thread_data->display, root_window, 0, 0, 1, 1, 0, screen_depth, @@ -1231,15 +1231,17 @@ static HANDLE X11DRV_CLIPBOARD_ImportCompoundText(Display *display, Window w, At HANDLE hUnicodeText; XTextProperty txtprop; - wine_tsx11_lock(); - if (!XGetTextProperty(display, w, &txtprop, prop)) + if (!X11DRV_CLIPBOARD_ReadProperty(display, w, prop, &txtprop.value, &txtprop.nitems)) { - wine_tsx11_unlock(); return 0; } + txtprop.encoding = x11drv_atom(COMPOUND_TEXT); + txtprop.format = 8; + wine_tsx11_lock(); XmbTextPropertyToTextList(display, &txtprop, &srcstr, &count); wine_tsx11_unlock(); + HeapFree(GetProcessHeap(), 0, txtprop.value); TRACE("Importing %d line(s)\n", count); @@ -1276,7 +1278,6 @@ static HANDLE X11DRV_CLIPBOARD_ImportCompoundText(Display *display, Window w, At wine_tsx11_lock(); XFreeStringList(srcstr); - XFree(txtprop.value); wine_tsx11_unlock(); return hUnicodeText; @@ -2017,27 +2018,23 @@ static BOOL X11DRV_CLIPBOARD_ReadSelectionData(Display *display, LPWINE_CLIPDATA /************************************************************************** - * X11DRV_CLIPBOARD_ReadProperty - * Reads the contents of the X selection property. + * X11DRV_CLIPBOARD_GetProperty + * Gets type, data and size. */ -static BOOL X11DRV_CLIPBOARD_ReadProperty(Display *display, Window w, Atom prop, - unsigned char** data, unsigned long* datasize) +static BOOL X11DRV_CLIPBOARD_GetProperty(Display *display, Window w, Atom prop, + Atom *atype, unsigned char** data, unsigned long* datasize) { - Atom atype = AnyPropertyType; int aformat; unsigned long pos = 0, nitems, remain, count; unsigned char *val = NULL, *buffer; - if (prop == None) - return FALSE; - TRACE("Reading property %lu from X window %lx\n", prop, w); for (;;) { wine_tsx11_lock(); if (XGetWindowProperty(display, w, prop, pos, INT_MAX / 4, False, - AnyPropertyType, &atype, &aformat, &nitems, &remain, &buffer) != Success) + AnyPropertyType, atype, &aformat, &nitems, &remain, &buffer) != Success) { wine_tsx11_unlock(); WARN("Failed to read property\n"); @@ -2078,6 +2075,86 @@ static BOOL X11DRV_CLIPBOARD_ReadProperty(Display *display, Window w, Atom prop, } +/************************************************************************** + * X11DRV_CLIPBOARD_ReadProperty + * Reads the contents of the X selection property. + */ +static BOOL X11DRV_CLIPBOARD_ReadProperty(Display *display, Window w, Atom prop, + unsigned char** data, unsigned long* datasize) +{ + Atom atype; + XEvent xe; + + if (prop == None) + return FALSE; + + if (!X11DRV_CLIPBOARD_GetProperty(display, w, prop, &atype, data, datasize)) + return FALSE; + + wine_tsx11_lock(); + while (XCheckTypedWindowEvent(display, w, PropertyNotify, &xe)) + ; + wine_tsx11_unlock(); + + if (atype == x11drv_atom(INCR)) + { + unsigned char *buf = *data; + unsigned long bufsize = 0; + + for (;;) + { + int i; + unsigned char *prop_data, *tmp; + unsigned long prop_size; + + /* Wait until PropertyNotify is received */ + for (i = 0; i < SELECTION_RETRIES; i++) + { + Bool res; + + wine_tsx11_lock(); + res = XCheckTypedWindowEvent(display, w, PropertyNotify, &xe); + wine_tsx11_unlock(); + if (res && xe.xproperty.atom == prop && + xe.xproperty.state == PropertyNewValue) + break; + usleep(SELECTION_WAIT); + } + + if (i >= SELECTION_RETRIES || + !X11DRV_CLIPBOARD_GetProperty(display, w, prop, &atype, &prop_data, &prop_size)) + { + HeapFree(GetProcessHeap(), 0, buf); + return FALSE; + } + + /* Retrieved entire data. */ + if (prop_size == 0) + { + HeapFree(GetProcessHeap(), 0, prop_data); + *data = buf; + *datasize = bufsize; + return TRUE; + } + + tmp = HeapReAlloc(GetProcessHeap(), 0, buf, bufsize + prop_size + 1); + if (!tmp) + { + HeapFree(GetProcessHeap(), 0, buf); + return FALSE; + } + + buf = tmp; + memcpy(buf + bufsize, prop_data, prop_size + 1); + bufsize += prop_size; + HeapFree(GetProcessHeap(), 0, prop_data); + } + } + + return TRUE; +} + + /************************************************************************** * CLIPBOARD_SerializeMetafile */ diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 90ec95ad3bb..8a5a4b531c3 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -580,6 +580,7 @@ enum x11drv_atoms FIRST_XATOM = XA_LAST_PREDEFINED + 1, XATOM_CLIPBOARD = FIRST_XATOM, XATOM_COMPOUND_TEXT, + XATOM_INCR, XATOM_MULTIPLE, XATOM_SELECTION_DATA, XATOM_TARGETS, diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 15694816876..c0c07c52779 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -115,6 +115,7 @@ static const char * const atom_names[NB_XATOMS - FIRST_XATOM] = { "CLIPBOARD", "COMPOUND_TEXT", + "INCR", "MULTIPLE", "SELECTION_DATA", "TARGETS",