XQuartz: pbproxy: The greedy CLIPBOARD handling now works for text.

This change adds some [self own_clipboard] calls in the necessary places to get the proper greedy behavior.

UTF8_STRING and STRING properties seem to work well now with the test cases (PRIMARY, and CLIPBOARD).  I can copy from several different X apps, and have the behavior be correct when pasting.  I also verified that quartz-wm isn't doing the copying, by disabling the quartz-wm paths.
(cherry picked from commit 934669f732c28f07b9d934d8f8f0b63ccfebd900)
This commit is contained in:
George Peter Staplin 2008-09-16 21:09:22 -06:00 committed by Jeremy Huddleston
parent 7c2eb3d41a
commit 23ec8261b6
2 changed files with 57 additions and 27 deletions

View File

@ -21,12 +21,7 @@ CFRunLoopSourceRef x_dpy_source;
/* Timestamp when the X server last told us it's active */ /* Timestamp when the X server last told us it's active */
static Time last_activation_time; static Time last_activation_time;
static FILE *getSelectionLog(void) {
return fopen("/tmp/selection.log", "a");
}
static void x_event_apple_wm_notify(XAppleWMNotifyEvent *e) { static void x_event_apple_wm_notify(XAppleWMNotifyEvent *e) {
FILE *fp = getSelectionLog();
switch (e->type - x_apple_wm_event_base) { switch (e->type - x_apple_wm_event_base) {
case AppleWMActivationNotify: case AppleWMActivationNotify:
@ -45,19 +40,15 @@ static void x_event_apple_wm_notify(XAppleWMNotifyEvent *e) {
break; break;
case AppleWMPasteboardNotify: case AppleWMPasteboardNotify:
fprintf(fp, "AppleWMPasteboardNotify\n");
switch (e->kind) { switch (e->kind) {
case AppleWMCopyToPasteboard: case AppleWMCopyToPasteboard:
[x_selection_object () x_copy:e->time]; [x_selection_object () x_copy:e->time];
} }
break; break;
} }
fclose(fp);
} }
void x_input_run (void) { void x_input_run (void) {
FILE *fp = getSelectionLog();
while (XPending (x_dpy) != 0) { while (XPending (x_dpy) != 0) {
XEvent e; XEvent e;
@ -66,23 +57,18 @@ void x_input_run (void) {
switch (e.type) { switch (e.type) {
case SelectionClear: case SelectionClear:
fprintf(fp, "SelectionClear\n");
[x_selection_object () clear_event:&e.xselectionclear]; [x_selection_object () clear_event:&e.xselectionclear];
break; break;
case SelectionRequest: case SelectionRequest:
fprintf(fp, "SelectionRequest\n");
[x_selection_object () request_event:&e.xselectionrequest]; [x_selection_object () request_event:&e.xselectionrequest];
break; break;
case SelectionNotify: case SelectionNotify:
fprintf(fp, "SelectionNotify\n");
[x_selection_object () notify_event:&e.xselection]; [x_selection_object () notify_event:&e.xselection];
break; break;
case PropertyNotify: case PropertyNotify:
fprintf(fp, "PropertyNotify\n");
[x_selection_object () property_event:&e.xproperty]; [x_selection_object () property_event:&e.xproperty];
break; break;
@ -96,7 +82,6 @@ void x_input_run (void) {
XFlush(x_dpy); XFlush(x_dpy);
} }
fclose(fp);
} }
static int add_input_socket (int sock, CFOptionFlags callback_types, static int add_input_socket (int sock, CFOptionFlags callback_types,

View File

@ -619,6 +619,9 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop)
/* Someone's asking us for the data on the pasteboard */ /* Someone's asking us for the data on the pasteboard */
TRACE (); TRACE ();
/*NOT YET*/
return;
/* TODO We should also keep track of the time of the selection, and /* TODO We should also keep track of the time of the selection, and
* according to the ICCCM "refuse the request" if the event timestamp * according to the ICCCM "refuse the request" if the event timestamp
* is before we owned it. * is before we owned it.
@ -629,6 +632,8 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop)
* Perhaps we should just punt and ignore races. * Perhaps we should just punt and ignore races.
*/ */
DB ("e->target %s\n", XGetAtomName (x_dpy, e->target));
if (e->target == atoms->targets) if (e->target == atoms->targets)
{ {
/* The paste requestor wants to know what TARGETS we support. */ /* The paste requestor wants to know what TARGETS we support. */
@ -662,13 +667,19 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop)
[self release_pending]; [self release_pending];
DB ("notify_event\n");
if (None == e->property) { if (None == e->property) {
DB ("e->property is None.\n"); DB ("e->property is None.\n");
if (pbproxy_clipboard_to_pasteboard && e->selection == atoms->clipboard)
[self own_clipboard];
/* Nothing is selected. */ /* Nothing is selected. */
return; return;
} }
DB ("e->selection %s\n", XGetAtomName (x_dpy, e->selection));
DB ("e->property %s\n", XGetAtomName (x_dpy, e->property));
if (is_incr_type (e)) if (is_incr_type (e))
{ {
/* /*
@ -679,6 +690,14 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop)
if (get_property (e->requestor, e->property, &pdata, /*Delete*/ True, &type)) if (get_property (e->requestor, e->property, &pdata, /*Delete*/ True, &type))
{ {
/*
* The get_property error could have occured with the clipboard atom.
* Greedily own the clipboard again.
*/
if (pbproxy_clipboard_to_pasteboard && e->selection == atoms->clipboard)
[self own_clipboard];
return; return;
} }
@ -697,12 +716,20 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop)
/* We have the complete selection data.*/ /* We have the complete selection data.*/
[self handle_selection: e->selection type:type propdata:&pdata]; [self handle_selection: e->selection type:type propdata:&pdata];
DB ("handled selection with the first notify_event\n");
/*
* This may have been the end of the clipboard request from [self claim_clipboard].
* If so, then we should own the contents now.
*/
if (pbproxy_clipboard_to_pasteboard && e->selection == atoms->clipboard) if (pbproxy_clipboard_to_pasteboard && e->selection == atoms->clipboard)
[self own_clipboard]; [self own_clipboard];
} }
} }
/* This is used for INCR transfers. See the ICCCM for the details. */ /* This is used for INCR transfers. See the ICCCM for the details. */
/* This is used to retrieve PRIMARY and CLIPBOARD selections. */
- (void) property_event:(XPropertyEvent *)e - (void) property_event:(XPropertyEvent *)e
{ {
struct propdata pdata; struct propdata pdata;
@ -710,6 +737,10 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop)
TRACE (); TRACE ();
if (None != e->atom)
DB ("e->atom %s\n", XGetAtomName (x_dpy, e->atom));
if (None != pending.requestor && PropertyNewValue == e->state) if (None != pending.requestor && PropertyNewValue == e->state)
{ {
DB ("pending.requestor 0x%lx\n", pending.requestor); DB ("pending.requestor 0x%lx\n", pending.requestor);
@ -730,6 +761,7 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop)
if (pbproxy_clipboard_to_pasteboard && pending.selection == atoms->clipboard) if (pbproxy_clipboard_to_pasteboard && pending.selection == atoms->clipboard)
[self own_clipboard]; [self own_clipboard];
pending.propdata = null_propdata; pending.propdata = null_propdata;
pending.requestor = None; pending.requestor = None;
pending.selection = None; pending.selection = None;
@ -786,7 +818,7 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop)
DB ("%s\n", [pbtype cStringUsingEncoding:NSISOLatin1StringEncoding]); DB ("%s\n", [pbtype cStringUsingEncoding:NSISOLatin1StringEncoding]);
pbtypes = [NSArray arrayWithObject: pbtype]; pbtypes = [NSArray arrayWithObjects: pbtype, nil];
if (nil == pbtypes) if (nil == pbtypes)
{ {
DB ("error creating NSArray\n"); DB ("error creating NSArray\n");
@ -829,16 +861,20 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop)
if (nil == string) if (nil == string)
return; return;
pbtypes = [NSArray arrayWithObject:NSStringPboardType]; pbtypes = [NSArray arrayWithObjects:NSStringPboardType, nil];
if (nil != pbtypes) if (nil != pbtypes)
{ {
[_pasteboard declareTypes:pbtypes owner:self]; [_pasteboard declareTypes:pbtypes owner:self];
[_pasteboard setString:string forType:NSStringPboardType];
if (YES != [_pasteboard setString:string forType:NSStringPboardType]) {
DB ("_pasteboard setString:forType: failed!\n");
}
[pbtypes release]; [pbtypes release];
} }
[string release]; [string release];
DB ("done handling utf8 string\n");
} }
/* This handles the XA_STRING type, which should be in Latin-1. */ /* This handles the XA_STRING type, which should be in Latin-1. */
@ -852,7 +888,7 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop)
if (nil == string) if (nil == string)
return; return;
pbtypes = [NSArray arrayWithObject:NSStringPboardType]; pbtypes = [NSArray arrayWithObjects:NSStringPboardType, nil];
if (nil != pbtypes) if (nil != pbtypes)
{ {
@ -915,6 +951,16 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop)
/* NSPasteboard-required methods */ /* NSPasteboard-required methods */
- (void)paste:(id)sender
{
TRACE ();
}
- (void)pasteboard:(NSPasteboard *)pb provideDataForType:(NSString *)type
{
TRACE ();
}
- (void) pasteboardChangedOwner:(NSPasteboard *)sender - (void) pasteboardChangedOwner:(NSPasteboard *)sender
{ {
TRACE (); TRACE ();
@ -978,4 +1024,3 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop)
} }
@end @end