From a59c231559c1e7020ccc1feee98fe3759016d9eb Mon Sep 17 00:00:00 2001 From: George Peter Staplin Date: Tue, 16 Sep 2008 21:09:22 -0600 Subject: [PATCH] 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) --- hw/xquartz/pbproxy/x-input.m | 15 ------- hw/xquartz/pbproxy/x-selection.m | 69 ++++++++++++++++++++++++++------ 2 files changed, 57 insertions(+), 27 deletions(-) diff --git a/hw/xquartz/pbproxy/x-input.m b/hw/xquartz/pbproxy/x-input.m index f720af5ed..5261212e0 100644 --- a/hw/xquartz/pbproxy/x-input.m +++ b/hw/xquartz/pbproxy/x-input.m @@ -21,12 +21,7 @@ CFRunLoopSourceRef x_dpy_source; /* Timestamp when the X server last told us it's active */ static Time last_activation_time; -static FILE *getSelectionLog(void) { - return fopen("/tmp/selection.log", "a"); -} - static void x_event_apple_wm_notify(XAppleWMNotifyEvent *e) { - FILE *fp = getSelectionLog(); switch (e->type - x_apple_wm_event_base) { case AppleWMActivationNotify: @@ -45,19 +40,15 @@ static void x_event_apple_wm_notify(XAppleWMNotifyEvent *e) { break; case AppleWMPasteboardNotify: - fprintf(fp, "AppleWMPasteboardNotify\n"); - switch (e->kind) { case AppleWMCopyToPasteboard: [x_selection_object () x_copy:e->time]; } break; } - fclose(fp); } void x_input_run (void) { - FILE *fp = getSelectionLog(); while (XPending (x_dpy) != 0) { XEvent e; @@ -66,23 +57,18 @@ void x_input_run (void) { switch (e.type) { case SelectionClear: - fprintf(fp, "SelectionClear\n"); - [x_selection_object () clear_event:&e.xselectionclear]; break; case SelectionRequest: - fprintf(fp, "SelectionRequest\n"); [x_selection_object () request_event:&e.xselectionrequest]; break; case SelectionNotify: - fprintf(fp, "SelectionNotify\n"); [x_selection_object () notify_event:&e.xselection]; break; case PropertyNotify: - fprintf(fp, "PropertyNotify\n"); [x_selection_object () property_event:&e.xproperty]; break; @@ -96,7 +82,6 @@ void x_input_run (void) { XFlush(x_dpy); } - fclose(fp); } static int add_input_socket (int sock, CFOptionFlags callback_types, diff --git a/hw/xquartz/pbproxy/x-selection.m b/hw/xquartz/pbproxy/x-selection.m index 49f74554a..0feb4fd47 100644 --- a/hw/xquartz/pbproxy/x-selection.m +++ b/hw/xquartz/pbproxy/x-selection.m @@ -619,6 +619,9 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop) /* Someone's asking us for the data on the pasteboard */ TRACE (); + /*NOT YET*/ + return; + /* TODO We should also keep track of the time of the selection, and * according to the ICCCM "refuse the request" if the event timestamp * is before we owned it. @@ -628,7 +631,9 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop) * may be set to CurrentTime or a time, so that makes it a bit different. * Perhaps we should just punt and ignore races. */ - + + DB ("e->target %s\n", XGetAtomName (x_dpy, e->target)); + if (e->target == atoms->targets) { /* The paste requestor wants to know what TARGETS we support. */ @@ -661,14 +666,20 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop) TRACE (); [self release_pending]; - - DB ("notify_event\n"); + if (None == e->property) { DB ("e->property is None.\n"); + + if (pbproxy_clipboard_to_pasteboard && e->selection == atoms->clipboard) + [self own_clipboard]; + /* Nothing is selected. */ 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)) { /* @@ -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)) { + /* + * 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; } @@ -697,18 +716,30 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop) /* We have the complete selection data.*/ [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) [self own_clipboard]; } } /* 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 { struct propdata pdata; Atom type; TRACE (); + + if (None != e->atom) + DB ("e->atom %s\n", XGetAtomName (x_dpy, e->atom)); + if (None != pending.requestor && PropertyNewValue == e->state) { @@ -726,10 +757,11 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop) if (0 == pdata.length) { /* We completed the transfer. */ - [self handle_selection: pending.selection type: type propdata: &pending.propdata]; + [self handle_selection:pending.selection type:type propdata:&pending.propdata]; if (pbproxy_clipboard_to_pasteboard && pending.selection == atoms->clipboard) [self own_clipboard]; + pending.propdata = null_propdata; pending.requestor = None; pending.selection = None; @@ -738,7 +770,7 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop) { [self append_to_pending: &pdata requestor: e->window]; } - } + } } - (void) handle_targets: (Atom)selection propdata:(struct propdata *)pdata @@ -786,7 +818,7 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop) DB ("%s\n", [pbtype cStringUsingEncoding:NSISOLatin1StringEncoding]); - pbtypes = [NSArray arrayWithObject: pbtype]; + pbtypes = [NSArray arrayWithObjects: pbtype, nil]; if (nil == pbtypes) { DB ("error creating NSArray\n"); @@ -823,22 +855,26 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop) NSArray *pbtypes; TRACE (); - + string = [[NSString alloc] initWithBytes:pdata->data length:pdata->length encoding:NSUTF8StringEncoding]; if (nil == string) return; - pbtypes = [NSArray arrayWithObject:NSStringPboardType]; + pbtypes = [NSArray arrayWithObjects:NSStringPboardType, nil]; if (nil != pbtypes) { [_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]; } - [string release]; + + DB ("done handling utf8 string\n"); } /* 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) return; - pbtypes = [NSArray arrayWithObject:NSStringPboardType]; + pbtypes = [NSArray arrayWithObjects:NSStringPboardType, nil]; if (nil != pbtypes) { @@ -915,6 +951,16 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop) /* NSPasteboard-required methods */ +- (void)paste:(id)sender +{ + TRACE (); +} + +- (void)pasteboard:(NSPasteboard *)pb provideDataForType:(NSString *)type +{ + TRACE (); +} + - (void) pasteboardChangedOwner:(NSPasteboard *)sender { TRACE (); @@ -978,4 +1024,3 @@ convert_1 (XSelectionRequestEvent *e, NSString *data, Atom target, Atom prop) } @end -