XQuartz: pbproxy: Add COMPOUND_TEXT handling. Do misc. cleanups with testing
to verify that the behavior didn't change.
main.m: XInternAtom compound_text, and atom_pair.
pbproxy.h: Add compound_text and atom_pair to the struct atom_list.
x-selection.m: Add an #include of Xutil.h. Refactor the reply struct
initialization to be done in a common place. Add send_reply: to simplify
the code a bit more. Add send_compound_text: which handles the
COMPOUND_TEXT type. Add the beginnings of a send_multiple:. Change
handle_image:extension: to handle_image:. The extension: message isn't
needed anymore.
(cherry picked from commit 1e9460abdf
)
This commit is contained in:
parent
00bfbee59f
commit
749bdf19b2
|
@ -77,6 +77,8 @@ static void x_init (void) {
|
|||
atoms->incr = XInternAtom (x_dpy, "INCR", False);
|
||||
atoms->atom = XInternAtom (x_dpy, "ATOM", False);
|
||||
atoms->clipboard_manager = XInternAtom (x_dpy, "CLIPBOARD_MANAGER", False);
|
||||
atoms->compound_text = XInternAtom (x_dpy, "COMPOUND_TEXT", False);
|
||||
atoms->atom_pair = XInternAtom (x_dpy, "ATOM_PAIR", False);
|
||||
|
||||
if (!XAppleWMQueryExtension (x_dpy, &x_apple_wm_event_base,
|
||||
&x_apple_wm_error_base)) {
|
||||
|
|
|
@ -25,7 +25,8 @@ extern int x_apple_wm_event_base, x_apple_wm_error_base;
|
|||
|
||||
struct atom_list {
|
||||
Atom primary, clipboard, text, utf8_string, string, targets, multiple,
|
||||
cstring, image_png, image_jpeg, incr, atom, clipboard_manager;
|
||||
cstring, image_png, image_jpeg, incr, atom, clipboard_manager,
|
||||
compound_text, atom_pair;
|
||||
};
|
||||
|
||||
extern struct atom_list *atoms;
|
||||
|
|
|
@ -338,6 +338,7 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret)
|
|||
#if 0
|
||||
if ([_pasteboard changeCount] != _my_last_change)
|
||||
{
|
||||
/*gstaplin: we should perhaps investigate something like this branch above...*/
|
||||
if ([_pasteboard availableTypeFromArray: _known_types] != nil)
|
||||
{
|
||||
/* Pasteboard has data we should proxy; I think it makes
|
||||
|
@ -493,6 +494,25 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret)
|
|||
atoms->clipboard));
|
||||
}
|
||||
|
||||
- (void) init_reply:(XEvent *)reply request:(XSelectionRequestEvent *)e
|
||||
{
|
||||
reply->xselection.type = SelectionNotify;
|
||||
reply->xselection.selection = e->selection;
|
||||
reply->xselection.target = e->target;
|
||||
reply->xselection.requestor = e->requestor;
|
||||
reply->xselection.time = e->time;
|
||||
reply->xselection.property = None;
|
||||
}
|
||||
|
||||
- (void) send_reply:(XEvent *)reply
|
||||
{
|
||||
/*
|
||||
* We are supposed to use an empty event mask, and not propagate
|
||||
* the event, according to the ICCCM.
|
||||
*/
|
||||
XSendEvent (x_dpy, reply->xselection.requestor, False, 0, reply);
|
||||
}
|
||||
|
||||
/*
|
||||
* This responds to a TARGETS request.
|
||||
* The result is a list of a ATOMs that correspond to the types available
|
||||
|
@ -506,27 +526,24 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret)
|
|||
XEvent reply;
|
||||
NSArray *pbtypes;
|
||||
|
||||
reply.xselection.type = SelectionNotify;
|
||||
reply.xselection.selection = e->selection;
|
||||
reply.xselection.target = e->target;
|
||||
reply.xselection.requestor = e->requestor;
|
||||
reply.xselection.time = e->time;
|
||||
reply.xselection.property = None;
|
||||
[self init_reply:&reply request:e];
|
||||
|
||||
pbtypes = [_pasteboard types];
|
||||
if (pbtypes)
|
||||
{
|
||||
long list[5];
|
||||
long list[6];
|
||||
long count = 0;
|
||||
|
||||
if ([pbtypes containsObject:NSStringPboardType])
|
||||
{
|
||||
/* We have a string type that we can convert to a UTF8 or Latin-1 string. */
|
||||
/* We have a string type that we can convert to UTF8, or Latin-1... */
|
||||
DB ("NSStringPboardType\n");
|
||||
list[count] = atoms->utf8_string;
|
||||
++count;
|
||||
list[count] = atoms->string;
|
||||
++count;
|
||||
list[count] = atoms->compound_text;
|
||||
++count;
|
||||
}
|
||||
|
||||
if ([pbtypes containsObject:NSTIFFPboardType]
|
||||
|
@ -540,7 +557,6 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret)
|
|||
++count;
|
||||
}
|
||||
|
||||
|
||||
if (count)
|
||||
{
|
||||
/* We have a list of ATOMs to send. */
|
||||
|
@ -551,46 +567,10 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We are supposed to use an empty event mask, and not propagate
|
||||
* the event, according to the ICCCM.
|
||||
*/
|
||||
XSendEvent (x_dpy, e->requestor, False, 0, &reply);
|
||||
[self send_reply:&reply];
|
||||
}
|
||||
|
||||
|
||||
/*TODO finish this - it's flawed. */
|
||||
- (void) send_multiple:(XSelectionRequestEvent *)e
|
||||
{
|
||||
#if 0
|
||||
XEvent reply;
|
||||
int i, nitems;
|
||||
unsigned long *atoms;
|
||||
|
||||
if (None == e->property)
|
||||
return;
|
||||
|
||||
atoms = read_prop_32 (e->requestor, e->property, &nitems);
|
||||
|
||||
if (atoms != NULL)
|
||||
{
|
||||
data = [_pasteboard stringForType:NSStringPboardType];
|
||||
|
||||
for (i = 0; i < nitems; i += 2)
|
||||
{
|
||||
Atom target = atoms[i], prop = atoms[i+1];
|
||||
|
||||
atoms[i+1] = convert_1 (e, data, target, prop);
|
||||
}
|
||||
|
||||
XChangeProperty (x_dpy, e->requestor, e->property, target,
|
||||
32, PropModeReplace, (unsigned char *) atoms,
|
||||
nitems);
|
||||
XFree (atoms);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void) send_string:(XSelectionRequestEvent *)e utf8:(BOOL)utf8
|
||||
{
|
||||
XEvent reply;
|
||||
|
@ -598,12 +578,7 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret)
|
|||
|
||||
TRACE ();
|
||||
|
||||
reply.xselection.type = SelectionNotify;
|
||||
reply.xselection.selection = e->selection;
|
||||
reply.xselection.target = e->target;
|
||||
reply.xselection.requestor = e->requestor;
|
||||
reply.xselection.time = e->time;
|
||||
reply.xselection.property = None;
|
||||
[self init_reply:&reply request:e];
|
||||
|
||||
pbtypes = [_pasteboard types];
|
||||
|
||||
|
@ -615,7 +590,8 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret)
|
|||
const char *bytes;
|
||||
NSUInteger length;
|
||||
|
||||
if (utf8) {
|
||||
if (utf8)
|
||||
{
|
||||
bytes = [data UTF8String];
|
||||
/*
|
||||
* We don't want the UTF-8 string length here.
|
||||
|
@ -623,7 +599,9 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret)
|
|||
*/
|
||||
length = [data lengthOfBytesUsingEncoding:NSASCIIStringEncoding];
|
||||
DB ("UTF-8\n");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
DB ("Latin-1\n");
|
||||
bytes = [data cStringUsingEncoding:NSISOLatin1StringEncoding];
|
||||
length = [data lengthOfBytesUsingEncoding:NSASCIIStringEncoding];
|
||||
|
@ -638,10 +616,77 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret)
|
|||
}
|
||||
}
|
||||
|
||||
/* Always send a response, even if the property value is None. */
|
||||
XSendEvent (x_dpy, e->requestor, False, 0, &reply);
|
||||
[self send_reply:&reply];
|
||||
}
|
||||
|
||||
- (void) send_compound_text:(XSelectionRequestEvent *)e
|
||||
{
|
||||
XEvent reply;
|
||||
NSArray *pbtypes;
|
||||
|
||||
TRACE ();
|
||||
|
||||
[self init_reply:&reply request:e];
|
||||
|
||||
pbtypes = [_pasteboard types];
|
||||
|
||||
if ([pbtypes containsObject: NSStringPboardType])
|
||||
{
|
||||
NSString *data = [_pasteboard stringForType:NSStringPboardType];
|
||||
if (nil != data)
|
||||
{
|
||||
/*
|
||||
* Cast to (void *) to avoid a const warning.
|
||||
* AFAIK Xutf8TextListToTextProperty does not modify the input memory.
|
||||
*/
|
||||
void *utf8 = (void *)[data UTF8String];
|
||||
char *list[] = { utf8, NULL };
|
||||
XTextProperty textprop;
|
||||
|
||||
textprop.value = NULL;
|
||||
|
||||
if (Success == Xutf8TextListToTextProperty (x_dpy, list, 1,
|
||||
XCompoundTextStyle,
|
||||
&textprop))
|
||||
{
|
||||
|
||||
if (8 != textprop.format)
|
||||
DB ("textprop.format is unexpectedly not 8 - it's %d instead\n",
|
||||
textprop.format);
|
||||
|
||||
XChangeProperty (x_dpy, e->requestor, e->property,
|
||||
atoms->compound_text, textprop.format,
|
||||
PropModeReplace, textprop.value,
|
||||
textprop.nitems);
|
||||
|
||||
reply.xselection.property = e->property;
|
||||
}
|
||||
|
||||
if (textprop.value)
|
||||
XFree (textprop.value);
|
||||
}
|
||||
}
|
||||
|
||||
[self send_reply:&reply];
|
||||
}
|
||||
|
||||
- (void) send_multiple:(XSelectionRequestEvent *)e
|
||||
{
|
||||
XEvent reply;
|
||||
|
||||
TRACE ();
|
||||
|
||||
[self init_reply:&reply request:e];
|
||||
|
||||
if (None != e->property)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[self send_reply:&reply];
|
||||
}
|
||||
|
||||
|
||||
- (void) send_image:(XSelectionRequestEvent *)e
|
||||
{
|
||||
XEvent reply;
|
||||
|
@ -651,12 +696,7 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret)
|
|||
|
||||
TRACE ();
|
||||
|
||||
reply.xselection.type = SelectionNotify;
|
||||
reply.xselection.selection = e->selection;
|
||||
reply.xselection.target = e->target;
|
||||
reply.xselection.requestor = e->requestor;
|
||||
reply.xselection.time = e->time;
|
||||
reply.xselection.property = None;
|
||||
[self init_reply:&reply request:e];
|
||||
|
||||
pbtypes = [_pasteboard types];
|
||||
|
||||
|
@ -678,7 +718,7 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret)
|
|||
if (type)
|
||||
{
|
||||
NSData *data;
|
||||
data = [_pasteboard dataForType: type];
|
||||
data = [_pasteboard dataForType:type];
|
||||
|
||||
if (data)
|
||||
{
|
||||
|
@ -709,8 +749,7 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret)
|
|||
}
|
||||
}
|
||||
}
|
||||
/* Always send a response, even if the property value is None. */
|
||||
XSendEvent (x_dpy, e->requestor, False, 0, &reply);
|
||||
[self send_reply:&reply];
|
||||
}
|
||||
|
||||
- (void)send_none:(XSelectionRequestEvent *)e
|
||||
|
@ -719,15 +758,8 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret)
|
|||
|
||||
TRACE ();
|
||||
|
||||
reply.xselection.type = SelectionNotify;
|
||||
reply.xselection.selection = e->selection;
|
||||
reply.xselection.target = e->target;
|
||||
reply.xselection.requestor = e->requestor;
|
||||
reply.xselection.time = e->time;
|
||||
reply.xselection.property = None;
|
||||
|
||||
/* Always send a response, even if the property value is None. */
|
||||
XSendEvent (x_dpy, e->requestor, False, 0, &reply);
|
||||
[self init_reply:&reply request:e];
|
||||
[self send_reply:&reply];
|
||||
}
|
||||
|
||||
|
||||
|
@ -746,7 +778,8 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret)
|
|||
* Perhaps we should just punt and ignore races.
|
||||
*/
|
||||
|
||||
/*TODO handle COMPOUND_STRING... We need a test app*/
|
||||
/*TODO we need a COMPOUND_TEXT test app*/
|
||||
/*TODO we need a MULTIPLE test app*/
|
||||
|
||||
DB ("e->target %s\n", XGetAtomName (x_dpy, e->target));
|
||||
|
||||
|
@ -767,6 +800,14 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret)
|
|||
{
|
||||
[self send_string:e utf8:NO];
|
||||
}
|
||||
else if (e->target == atoms->compound_text)
|
||||
{
|
||||
[self send_compound_text:e];
|
||||
}
|
||||
else if (e->target == atoms->multiple)
|
||||
{
|
||||
[self send_multiple:e];
|
||||
}
|
||||
else if (e->target == atoms->image_png || e->target == atoms->image_jpeg)
|
||||
{
|
||||
[self send_image:e];
|
||||
|
@ -919,7 +960,7 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret)
|
|||
|
||||
/* This handles the image type of selection (typically in CLIPBOARD). */
|
||||
/* We convert to a TIFF, so that other applications can paste more easily. */
|
||||
- (void) handle_image: (struct propdata *)pdata extension:(NSString *)fileext
|
||||
- (void) handle_image: (struct propdata *)pdata
|
||||
{
|
||||
NSArray *pbtypes;
|
||||
NSUInteger length;
|
||||
|
@ -1041,11 +1082,11 @@ read_prop_32 (Window id, Atom prop, int *nitems_ret)
|
|||
}
|
||||
else if (type == atoms->image_png)
|
||||
{
|
||||
[self handle_image:pdata extension:@".png"];
|
||||
[self handle_image:pdata];
|
||||
}
|
||||
else if (type == atoms->image_jpeg)
|
||||
{
|
||||
[self handle_image:pdata extension:@".jpeg"];
|
||||
[self handle_image:pdata];
|
||||
}
|
||||
else if (type == atoms->utf8_string)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue
Block a user