Fix Copy/Paste problems on X11

The target of the TARGETS type should be XA_ATOM and not XA_TARGETS when
requested. Since we are sending a number of ATOMS the size should be set
to the integer size and not the char size.

The size field of the atoms is also the number of atoms and not the size
of the array. This caused some clients to wrongly interpret the data and
read garbage in the X11 packet.

I also add the more modern representation for UTF-8 and clarify the
error message if a client attempts to request a type we don't know
about.

This fixes #10431
This commit is contained in:
Hein-Pieter van Braam 2018-01-29 00:33:57 +01:00
parent 4caadae0f1
commit fb60f2dbe6
1 changed files with 29 additions and 11 deletions

View File

@ -1862,8 +1862,12 @@ void OS_X11::process_xevents() {
e = event; e = event;
req = &(e.xselectionrequest); req = &(e.xselectionrequest);
if (req->target == XA_STRING || req->target == XInternAtom(x11_display, "COMPOUND_TEXT", 0) || if (req->target == XInternAtom(x11_display, "UTF8_STRING", 0) ||
req->target == XInternAtom(x11_display, "UTF8_STRING", 0)) { req->target == XInternAtom(x11_display, "COMPOUND_TEXT", 0) ||
req->target == XInternAtom(x11_display, "TEXT", 0) ||
req->target == XA_STRING ||
req->target == XInternAtom(x11_display, "text/plain;charset=utf-8", 0) ||
req->target == XInternAtom(x11_display, "text/plain", 0)) {
CharString clip = OS::get_clipboard().utf8(); CharString clip = OS::get_clipboard().utf8();
XChangeProperty(x11_display, XChangeProperty(x11_display,
req->requestor, req->requestor,
@ -1876,26 +1880,40 @@ void OS_X11::process_xevents() {
respond.xselection.property = req->property; respond.xselection.property = req->property;
} else if (req->target == XInternAtom(x11_display, "TARGETS", 0)) { } else if (req->target == XInternAtom(x11_display, "TARGETS", 0)) {
Atom data[2]; Atom data[7];
data[0] = XInternAtom(x11_display, "UTF8_STRING", 0); data[0] = XInternAtom(x11_display, "TARGETS", 0);
data[1] = XA_STRING; data[1] = XInternAtom(x11_display, "UTF8_STRING", 0);
XChangeProperty(x11_display, req->requestor, req->property, req->target, data[2] = XInternAtom(x11_display, "COMPOUND_TEXT", 0);
8, PropModeReplace, (unsigned char *)&data, data[3] = XInternAtom(x11_display, "TEXT", 0);
sizeof(data)); data[4] = XA_STRING;
data[5] = XInternAtom(x11_display, "text/plain;charset=utf-8", 0);
data[6] = XInternAtom(x11_display, "text/plain", 0);
XChangeProperty(x11_display,
req->requestor,
req->property,
XA_ATOM,
32,
PropModeReplace,
(unsigned char *)&data,
sizeof(data) / sizeof(data[0]));
respond.xselection.property = req->property; respond.xselection.property = req->property;
} else { } else {
printf("No String %x\n", char *targetname = XGetAtomName(x11_display, req->target);
(int)req->target); printf("No Target '%s'\n", targetname);
if (targetname)
XFree(targetname);
respond.xselection.property = None; respond.xselection.property = None;
} }
respond.xselection.type = SelectionNotify; respond.xselection.type = SelectionNotify;
respond.xselection.display = req->display; respond.xselection.display = req->display;
respond.xselection.requestor = req->requestor; respond.xselection.requestor = req->requestor;
respond.xselection.selection = req->selection; respond.xselection.selection = req->selection;
respond.xselection.target = req->target; respond.xselection.target = req->target;
respond.xselection.time = req->time; respond.xselection.time = req->time;
XSendEvent(x11_display, req->requestor, 0, 0, &respond); XSendEvent(x11_display, req->requestor, True, NoEventMask, &respond);
XFlush(x11_display); XFlush(x11_display);
} break; } break;