Xpra: Ticket #272: fix/improve MS Windows clipboard handling

Split from #11. Please see wiki/Clipboard first.

This should take of copy+paste from server to client.

There may well be some cases where this causes problems, or where the user chooses to sync with a single clipboard, so we probably want to add a new UI and command line option (win32 clients only):

--clipboard-sync=primary|secondary|clipboard|all

"all" would be the new "auto" mode.



Thu, 28 Feb 2013 16:43:44 GMT - Antoine Martin: status, description changed


Mon, 04 Mar 2013 12:24:22 GMT - Antoine Martin: owner, status changed

mostly done in r2855, not done the UI since the default is probably better than what we had before.

Despite knowing very well that I needed to turn off VirtualBox's own clipboard synchronization, I forgot about it and thought the whole thing was broken... beware when testing!


Fri, 08 Mar 2013 04:09:43 GMT - alas:

With a Fedora 18 server with xpra 0.9.0 and a windows client with 0.8.7 I have found the following behaviors.

  1. Copying on the windows client loads the content into all three of the server clipboards (primary, secondary & clipboard). Pasting works consistently in this case.
  1. Copying in the xpra window loads the data into the primary clipboard and the clipboard clipboard, but not the secondary clipboard.
  1. The first such copy will produce correct results when pasting to the windows client. Copying a second (or subsequent) set of data will update the data in both the primary and clipboard clipboards, but attempts to paste into the windows client will result in pasting the first set of data repeatedly. (The pasting will behave correctly within the xpra window(s), meanwhile.)
  1. Highlighting and deleting data in the xpra window will copy that data to the primary clipboard (leading me to believe that it is used as an 'undo' storage location), while it will clear the secondary clipboard (if not already clear) and it will also (often, but somewhat erratically) clear the clipboard clipboard. --> At this point, however, pasting to the windows client will produce unpredictable results, often the pasting of some portion of the "deleted" text stored in the primary clipboard.
  1. Once the clipboard clipboard has thusly been cleared, whatever is next copied will be "transmitted" to the windows client clipboard and can be pasted. (And will likewise continue to be repasted and repasted again, until another such deletion resets the clipboard, or something is copied anew from the windows client, filling all three clipboards.)
  1. Sometimes, however, the clipboard clipboard won't be cleared. In that case, the windows clipboard will continue to "resist" updating with any new copied data.
  1. I also noticed that calls with xclip to output the contents of the secondary clipboard always produced a debugging message from the client indicating that it was being asked for clipboard data when it wasn't expecting to be so queried. I take that to mean that the secondary clipboard is intended to be used for data from outside of the local environment.
  1. Windows also seems to have an "undo" clipboard somewhere, which occasionally seems to confuse matters if clipboard contents don't "initialize" when an xpra session starts, in which case- despite having recently copied something from the windows client environment (before beginning the xpra session), an attempt to paste into the xpra will paste no data... and if one then tries to paste back into the windows environment something random will be pasted (which may or may not be drawn from the windows "undo" clipboard in much the same way that pasting sometimes results in pulling "deleted" data from the primary clipboard).

In general:

  1. If all three clipboards have data then most likely the last copy was from the client.
  1. If the primary and clipboard clipboards have data, then the last copy was from within the xpra environment.
  1. If only the primary clipboard has data, then most likely there was a recent deletion.
  1. If the data in the primary clipboard and the clipboard clipboard are different, the clipboard will generally have the latest "copy data" while the primary will have the "delete data".

Unfortunately, the behavior is just buggy enough to resist a clear understanding or predictability.


Fri, 08 Mar 2013 04:42:23 GMT - Antoine Martin:

Do you have any log samples for each one?

  1. Copying on the windows client loads the content into all three of the server clipboards (primary, secondary & clipboard). Pasting works consistently in this case.

OK

  1. Copying in the xpra window loads the data into the primary clipboard and the clipboard clipboard, but not the secondary clipboard.

Not exactly: some applications load into 'primary', some in 'clipboard' and some (very rare) in 'secondary'. (and some in more than one at the same time) This is done by the application only and is totally beyond our control. Generally speaking, simply selecting/highlighting some text places it in 'primary', without any need to 'copy' it (via Control-C or via a menu). This is also why we really do not want to send clipboard data to the other end every time the clipboard contents change, but only when clipboard contents are requested by it. (imagine dragging the mouse over some large amount of text and the bandwidth hog this would generate)

  1. The first such copy will produce correct results when pasting to the windows client. Copying a second (or subsequent) set of data will update the data in both the primary and clipboard clipboards, but attempts to paste into the windows client will result in pasting the first set of data repeatedly. (The pasting will behave correctly within the xpra window(s), meanwhile.)

Confirmed. That's odd, sounds like something is owning the clipboard client side. I may knock up a test application we can run on win32 to show clipboard events. All the problems below may well be due to this one.

  1. Highlighting and deleting data in the xpra window will copy that data to the primary clipboard (leading me to believe that it is used as an 'undo' storage location), while it will clear the secondary clipboard (if not already clear) and it will also (often, but somewhat erratically) clear the clipboard clipboard. --> At this point, however, pasting to the windows client will produce unpredictable results, often the pasting of some portion of the "deleted" text stored in the primary clipboard.

I don't understand the 'undo' comments. And what do you mean by 'deleting data'?

  1. Once the clipboard clipboard has thusly been cleared, whatever is next copied will be "transmitted" to the windows client clipboard and can be pasted. (And will likewise continue to be repasted and repasted again, until another such deletion resets the clipboard, or something is copied anew from the windows client, filling all three clipboards.)

Due to (b), I'm not sure I understand.

  1. Sometimes, however, the clipboard clipboard won't be cleared. In that case, the windows clipboard will continue to "resist" updating with any new copied data.

Same. Why should it be cleared? Its contents are down to the application.

  1. I also noticed that calls with xclip to output the contents of the secondary clipboard always produced a debugging message from the client indicating that it was being asked for clipboard data when it wasn't expecting to be so queried. I take that to mean that the secondary clipboard is intended to be used for data from outside of the local environment.

Interesting, "secondary" is the only one that applications rarely ever touch. So this one will be set when the windows client copies something, and should not be updated thereafter - this may well lead me to the source of the problems. Could be a race since we set all three clipboards' ownership asynchronously.

  1. Windows also seems to have an "undo" clipboard somewhere, which occasionally seems to confuse matters if clipboard contents don't "initialize" when an xpra session starts, in which case- despite having recently copied something from the windows client environment (before beginning the xpra session), an attempt to paste into the xpra will paste no data... and if one then tries to paste back into the windows environment something random will be pasted (which may or may not be drawn from the windows "undo" clipboard in much the same way that pasting sometimes results in pulling "deleted" data from the primary clipboard).

Again, I don't know anything about this "undo" clipboard.. Initialization is tricky, who owns the clipboard at that point is not clear. IIRC, at the moment, the client should own it.

In general:

  1. If all three clipboards have data then most likely the last copy was from the client.

That would make sense since any copy events from the client sets all 3 clipboards as owned by the client.

  1. If the primary and clipboard clipboards have data, then the last copy was from within the xpra environment.

Also makes sense, X11 applications only interact with those two.

  1. If only the primary clipboard has data, then most likely there was a recent deletion.

What is a "deletion"?

  1. If the data in the primary clipboard and the clipboard clipboard are different, the clipboard will generally have the latest "copy data" while the primary will have the "delete data".

Hmmm, that I am not sure about at all. Applications control the clipboards and they can place anything they like in there at any point. We are only meant to grab all the updates and forward them to the client, so the client should always have the last clipboard update made.

Unfortunately, the behavior is just buggy enough to resist a clear understanding or predictability.

Indeed.

Let's see if fixing (2)a and/or (3) leads anywhere. Have you tried any of those tests with a simple xterm instead of chrome to rule out application specific behaviour?


Fri, 08 Mar 2013 14:19:11 GMT - Antoine Martin: attachment set

screenshot of the new clipboard debugging tool


Fri, 08 Mar 2013 14:56:24 GMT - Antoine Martin:

r2913 adds a clipboard debugging tool, and here is a screenshot: http://xpra.org/trac/raw-attachment/ticket/272/clipboard-tool.png


Hopefully this can help figure out what is going wrong. There is a new MS Windows beta package which includes this new tool (named GTK_Clipboard_Test.exe on win32)

Some initial notes and explanations


Fri, 08 Mar 2013 19:23:39 GMT - alas:

By "undo" clipboard I was referring to a buffer that is used when you right-click and select the undo option from the resultant drop-down menu. Since the primary stores selected data, I presumed that it was being used for this drop-down menu option. I still can't really think of any other reason to store selected data, either- especially before it is copied.

I failed, though to divorce the selecting of the data from the deleting of it (I guess I never thought to try that), so any reference I make to "deleting" data should be understood as being an assumed part of any selecting that is not a precursor to copying. Hence, a reference to a "recent deletion" is in fact a reference to a recent selection (with an anecdotal deletion of said selected data to follow, inconsequentially).

I should note, however, that in one instance of my testing I did inadvertantly paste blank data over a selected portion of text, deleting it but storing it in the primary clipboard... after which I used the right-click undo button to "restore" the data, in the process of which the primary was in fact cleared. I didn't repeat the process however, so I can make no estimation of how consistently it does this.

I should also note that the client's local clipboard seems to be another entity entirely from the clipboards of the xpra server (which you probably realize, but it seems like it should be said). Many times what is pasted in the windows client bears no resemblance whatsoever to the current contents of any of the three clipboards within the server.

In any case, I'll see if these new tools help me pin things down any more.


Sat, 09 Mar 2013 03:30:40 GMT - alas:

Ok, still using a Fedora 18 server with xpra 0.9.0 but now with win client 0.8.8 I had some different results which might shed some light on... something.

  1. With 0.8.8 client, a copy only seems to save to primary. Unfortunately, pasting to the xpra chrome browser seems to only use the clipboard... so the 0.8.8 client can't copy and paste from the client to an xpra chrome browser.
  1. Xpra xterm windows, however, copy to and from the primary, so anything copied from a win client can be "pasted" (Shift-Inserted) into an xterm.
  1. Xpra chrome browser copy (of highlighted text) copies to both primary and clipboard. Highlighting copies to primary, whether or not a copy operation is performed. Anything highlighted thusly can be inserted into an xterm window.
  1. Oddly, whatever is "owned" by the windows clipboard seems to be loaded into the primary clipboard when an xpra session begins. The first change of the contents of primary seems to be pasteable to the win client, but later changes are (generally) not acknowledged by the client clipboard operations. Sometimes, however, only a portion of that first change will be "acknowledged" by the win client. One letter. Three letters. 17 letters. Sometimes different numbers of characters from the same string... and sometimes (very occasionally) it will change for no apparent reason. (Ownership issues? Some portion of primary clipboard data "wins a race" over ownership issues? I have no idea.)
  1. Changes to primary can be made from selecting in chrome or in xterm and are equally likely (or rather, unlikely) to be acknowledged by win client.
  1. For client clipboard copying to be pasteable to a chrome browser it needs to be picked up by clipboard. For xterm it needs to be picked up by primary. The loading of all three in 0.8.7 seemed to work well for client to server. (Perhaps I just needed to use the binding command.)
  1. At one point selecting text in xpra chrome browsers was copying to the primary, but then hitting backspace was clearing primary. I can only guess that something caused the clipboard to copy the "blank" as if it were "selected" to the primary. It behaved this way consistently, until I stopped that xpra session. The three subsequent xpra sessions however did not clear the primary with backspaces of highlighted text.
  1. While the primary was being cleared by backspaces, inserting into an xterm pasted in whatever was in the primary before the last selection which was deleted by the backspace. This consistently occurred, with xterm insertions pasting in data that was no longer contained in any of the three clipboards. (Perhaps xterm has yet another "insertion clipboard" that it turns to if the primary has recently been cleared? Perhaps my server picked the wrong morning to quit sniffing glue?) Once the backspacing ceased clearing primary this behavior also ceased.
  1. Whatever I did, I could not find any correlation between secondary or clipboard with anything that successfully pasted into the win client. primary had some success, but very limited. IIRC testing with 0.8.7, when copying from the win client was stored in all three clipboards, had the effect of "renewing" the ability for things copied in an xpra browser to be pasted into the win client. I'm not sure if it was a coincidence, but perhaps the updating of the secondary by a win client copy operation then caused a reaction to the next primary change "similar to that seen when an xpra session first begins" which allows for the next "change" in the primary to be passed to the client?? (I realize that makes little sense, but perhaps there is some ownership issue that the use of the secondary "toggles"... and, judging from the fact that I saw pastings with no change in clipboard, I suspect it is primary that has some success being "read" by a window client)

Hopefully this is some use.


Sat, 09 Mar 2013 03:39:18 GMT - Antoine Martin:

When testing with 0.8.x, the clipboard uses the old code which selects a single target for the data exchanges (PRIMARY by default - though this can be changed via the tray menu). This explains most of what is reported in comment:7. (that and the bugs: (2)a and (3) from comment:3)

I don't think we will fix anything in the 0.8.x branch, it doesn't work great (and maybe the default remote clipboard should be CLIPBOARD instead of PRIMARY, this would make most people happier, except me an my xterms.. - but otherwise I think it works as was expected given the code that is in there) - 0.9.x is where it's at.


Tue, 19 Mar 2013 14:28:18 GMT - Antoine Martin:

So, we claim the CLIPBOARD selection, send the token to the client, the client then requests the contents as a 'UTF8_STRING' and we send back nothing... The client showed:

got token, selection=CLIPBOARD
do_selection_request_event(... selection=CLIPBOARD ..)
target for CLIPBOARD: UTF8_STRING
get clipboard from remote
got clipboard contents None
remote selection fetch timed out or empty

Questions:

This is giving me a headache! I'll try again tomorrow, but it looks like even the solution of going back to the one-to-one mapping may have the same issue..


Fri, 22 Mar 2013 13:17:56 GMT - Antoine Martin:


Changes are in r3038


How to test (steps most likely to exercise the fixes):

Then as above but reversed (though that was not a problem for me before)


Rants and notes:

But this wouldn't save us much since the big waste (often transferring clipboard contents before they are needed) cannot be avoided on win32.


Sat, 23 Mar 2013 05:54:56 GMT - Antoine Martin:

r3039 removes the ability to select the "old" merged clipboard from the tray menu, the "merged" clipboard code no longer exists.


Mon, 25 Mar 2013 19:56:04 GMT - alas:

I rebuilt a fedora 0.9.0 xpra and installed it server-side (3/25/13, built from svn source, said it included 3039). I am using the 0.9.0 windows client from beta 3/22/13. Testing with gtk_view_clipboard on xterms and google-chrome browser in xpra session.

Results:

This is as reproducible as a fecund teenager.

Copy something client-side to reset clipboard. ('old clipboard data') Select 'virii' from xterm. Paste (' virii')

Clipboard: (Got string selection data: '')
Primary: (Got string selection data: ' virii')
Secondary: (Got string selection data: '')
Paste into browser.
--nothing--

Type 'virii' into browser, select & copy.

"clipboard buffer contains blacklisted pattern 'virii' and has been dropped!"
Clipboard: (Got string selection data: 'virii')
Primary: (Got string selection data: 'virii')
Secondary: (Got string selection data: '')
Paste in txt: ('')

Type something else into browser & select & copy. Paste ('') Copy something client side to reset clipboard, then select & copy browser text. ('unhappy camper')

--->Clipboard: (Got string selection data: 'unhappy camper')
--> Primary: (Got string selection data: 'unhappy camper')
--> Secondary: (Got string selection data: '')

Select something from xterm. Paste ('unhappy camper')

--->Clipboard: (Got string selection data: 'unhappy camper')
--> Primary: (Got string selection data: ' :ApplyCaretV')
--> Secondary: (Got string selection data: '')

Copy something client-side to reset clipboard.

---> Clipboard: Owner changed, reason: new owner, new owner=0x400020
--> Primary: Owner changed, reason: new owner, new owner=0x400021
--> Secondary: Owner changed, reason: new owner, new owner=0x400022

(All 3 clipboards set to client-side copy data)

Now select from xterm (Paste: 'nted reached')

--> Primary: Owner changed, reason: new owner, new owner=0x80001b
Paste again: 'nted reached'
--->Clipboard: Got string selection data: ''
--> Primary: Got string selection data: 'nted reached')
--> Secondary: Got string selection data: ''

Mon, 25 Mar 2013 20:04:26 GMT - alas: status changed


Thu, 28 Mar 2013 18:47:58 GMT - Antoine Martin:

I was finding it very hard to read, understand and respond to comment:13, so I have edited the text to try to make it easier to refer to it (adding numbering) - apologies if I've somehow misinterpreted anything. In the future, please try adding: expected: X, result: Y and copying easily identifiable strings rather than random bits of text (ie: is "foiledcupcake" relevant in any way? does it help us understand/identify what we are looking at or what is expected to happen)


r3045 should help in this case (and when copying an empty string) as we now always force claim the selection, no matter what the contents received are. This should prevent the need to "reset the clipboard" by copying something client side (by virtually "copying" something every time something is received).


Sat, 30 Mar 2013 03:00:38 GMT - alas:

Firstly, you are correct. The text I used was irrelevant, with the exception of "virii".

I just rebuilt xpra 0.9.0 for fedora (got notification of 3046 during the svn update) and I am using the 0.9.0 xpra beta for windows client (downloaded 3/26/13).

I just repeated test 1: and I am still able to copy from an xterm (opened as a start-child on the server command line) to a client side txt file.

The behavior is similar to any other xpra-session to window client copy & pasting. The second set of text I selected (xterm copy), when I attempted to paste it into a windows client txt file I instead re-pasted the text from the first copy (select). Once I do a (pointless) copy on the client side, however, then the next selection in an xterm is likewise pasteable.

Test 2. was a repetition of the test, and the test is still repeatable as far as I can tell.

Tests 3,4&5. Were tests of the clipboard filter. We can forget about them.

Test 6 was merely to show that a copy from a browser was copying to both primary & clipboard (which I suspected but wanted to see).

Test 7 was to show that copy (select) from an xterm was solely copying to primary (as we would expect). It did indeed change contents of primary and did indeed NOT change contents of clipboard.

Test 8 was a documentation of the change of owner of all three clipboards when a copy was made client-side (which I hadn't expected, but which doesn't surprise me). I verified it by looking at the contents of the gtk_view_clipboard data and comparing it with the output of a control-V in a client-side txt file. Repeating, I get the same results.

debugging log:

clipboard raw -> wire: ('UTF8_STRING', 8, 'skadoopie\x00') -> ('bytes', 'skadooopie\x00')
process clipboard packet type=clipboard-pending-requests

(Note, I tested this after the Test 9 logs were generated, so the 'skadoopie' mentioned is a reference back to the previous contents, presumably.)

Test 9 was to see what happens to clipboards server-side when a copy is made from an xterm after all three clipboards were changed by the client-side copy. I was surprised to see clipboard and secondary both cleared. I was expecting to see the change in primary.

With the latest (as far as I can tell) server-side fedora and client side windows install- I still seem to be able to copy from an xterm to a client-side txt file (or anything else, really).

The client-side XPRA_CLIPBOARD_DEBUG=1 is telling me the following:

get clipboard from remote handler id=1
local_to_remote(CLIPBOARD) current_remote_clipboard=PRIMARY
process clipboard packet type=clipboard-contents
process clipboard contents, selection=PRIMARY, type=UTF8_STRING, format=8
_munge_wire_selection_to_raw(bytes, UTF8_STRING, 8, (type 'str'):10:[' ', 's', 'k', 'a', 'd', 'o', 'o', 'p', 'i', 'e'])
wire selection to raw, encoding=bytes, type=UTF8_STRING, format=8, len(data0=10
clipboard wire -> raw: ('UTF8_STRING, 8, 'bytes', ' skadoopie') -> ' skadoopie'
got clipboard contents91)=10 (type=UTF8_STRING, format=8)
get clipboard from remote result(1)={'data': ' skadoopie', 'type': 'UTF8_STRING', 'format': 8}
do_selection_get((GtkSelectionData at 0x18ef2c),0,0) calling selection_data.set(UTF8_STRING, 8, (type 'str'):10)

I hope this clarifies something. I will try to go through the fedora server and look for any and all possible other instances of xpra that might be hiding high or low and confusing the yum localinstall when I get a chance, but I think I got them all already.


Sat, 30 Mar 2013 08:54:39 GMT - Antoine Martin:

The log messages you just posted confirm what I suspected all along:

local_to_remote(CLIPBOARD) current_remote_clipboard=PRIMARY

This message was part of the merged clipboard, which has been removed in r3039.


You can verify that this code is no longer present in the source tree:

$ grep -r current_remote_clipboard ./trunk/src | wc -l
0


You should be using your own build system to make new win32 installers as needed, otherwise you have to wait for me to upload new ones - like this one I built yesterday:

4cb7e3dbefc710d7860512d21bd768a5  Xpra_Setup_0.9.0.exe

Mon, 01 Apr 2013 17:27:01 GMT - alas:

Is this an update that was included on the client-side (the windows), rather than the server side? (fedora in this testing case)?


Mon, 01 Apr 2013 18:55:00 GMT - Antoine Martin: summary changed

The clipboard changes will generally affect both sides since both sides have a clipboard to manage. That said:

Unless I have really messed something up, checking the revision number should be enough to verify that those changes are included. (either via "xpra info" for the server, or via "about" for win32 clients)


(I've also just changed the ticket title to reflect what has been done in this ticket)


Mon, 01 Apr 2013 23:44:38 GMT - alas:

Well, the windows client that includes the updates seems to be doing the trick. Some preliminary tests show that the previous bugs (not being able to copy two things in a row from an xpra session and paste them into a windows client environment) are fixed.

I'll do some more tests and see if there's anything I'm overlooking, but I think these changes make a windows client clipboard work consistently.


Tue, 02 Apr 2013 01:13:41 GMT - alas:

I spoke too soon. Windows to xpra and xpra to windows copying and pasting now works consistently and, newly, repeatedly. Copying in an xpra browser and then pasting somewhere else in the xpra session, however, does not work with this new client.

Some tests.

Newest (3/30/13) xpra win client 0.9.0, fedora xpra server 0.9.0 (3/27/13)
Start- copy something from win client environment.
Clipboard: 	Got string selection data: {copied data - expected}
Primary:	Got string selection data: {copied data - not unexpected}
Secondary:	Got string selection data: '' {not unexpected}
Copy something in xpra browser.
Selecting causes: Primary:	Owner changed, reason: new owner, new owner=0xc00326
Control-c:	Clipboard:	Owner changed, reason: new owner, new owner=0xc00326
		Clipboard:	Owner changed, reason: new owner, new owner=0x400020
Clipboard:	Got string selection data: '' {unexpected, ought to have copied data}
Primary:	Got string selection data: {copied data - not unexpected}
Secondary: 	Got string selection data: '' {expected}
Paste back into browser. Nothing happens. ('', presumably)
Copy something else in browser.
Selecting: Causes the same owner change as above (in fact, causes a new line for each character selected.)
Control-c: Causes the same two owner changes as above.
Clipboard: 	Got string selection data: '' {same unexpected lack of data}
Primary:	Got string selection data: {copied data - expected - oddly the extra space copied has been filtered fromthe copied data string.}
Secondary:	Got string selection data: '' {expected}
Paste back into browser. Nothing happens again.
Copy something client side.
Clipboard:	Got string selection data: {copied data - expected}
Primary:	Got string selection data: '' {not particularly expected}
Secondary:	Got string selection data: '' {expected}
Paste into xpra browser. {copied data - expected}
Copy something in xpra browser.
Same owner changes as above.
Clipboard:	Got string selection data: '' {now expected}
Primary:	Got string selection data: {copied data - now expected}
Secondary:	Got string selection data: '' {now expected}
Paste into txt file client-side: {copied data - expected}
Copy second something in xpra browser.
All same as first copy.
Paste into txt file client-side: {copied data - unexpectedly pleasant change}

Tue, 02 Apr 2013 08:49:18 GMT - Antoine Martin: owner, status changed

Yes, that's sort of expected now since we make the client claim to own the clipboard selection... so that's not going to be enough (though probably enough for your particular use case)


Wed, 03 Apr 2013 10:09:50 GMT - alas:

It occurs to me that you may have misunderstood what I meant by not being able to copy in an xpra session and then paste back somewhere else in an xpra session.

I don't mean from one xpra session to another, or even from one xpra browser to another. I mean that you can't copy & paste even within the same tab within an xpra browser. For instance, if you open an email with an xpra browser and want to reply- you can't copy even a sentence from the email itself into the reply within the same tab.

While it may be unusual for there to be enough in an email that you want to use copy and then paste in order to copy a portion of an email in order to then respond, rather than just re-typing the "quote", I think most users will nevertheless expect that level of functionality and would rather not have to retype everything when a "simple" copy and paste would make the process much easier.

Just wanted to clarify, because I realized that Smo had misunderstood and thought I meant copying from one xpra browser to another wasn't working, rather than copying & pasting within a single tab wasn't working.


Wed, 03 Apr 2013 17:48:03 GMT - Antoine Martin: status changed

Thanks for the clarification, I knew this was going to cause problems with local apps but I had forgotten that this would also interfere with cut&paste within the same app.

Since then, I've added some code to make it easier to test without having to run on win32 (to ease debugging): see r3048 and r3049. You can now run the client with a single gdk clipboard with:

XPRA_CLIPBOARDS=clipboard xpra attach ...

Or use the win32 translated clipboard code (which now amounts to pretty much the same thing since the default clipboard is "clipboard") with:

XPRA_TRANSLATED_CLIPBOARD=1 xpra attach ...

Interestingly, using either one of these options, I've managed to reproduce the same annoying behaviour on Fedora 18 with cinnamon: some applications are pulling the clipboard contents every 0.5 seconds, causing unnecessary network traffic. Running the same setup on a plain Xvfb does not have this problem. You can find a standalone test script in the tests/xpra tree as of r3050

The good thing about this is that it is now a hell of a lot easier to debug and test things.. but the bad thing is that I don't really know how to solve this.


Thu, 04 Apr 2013 12:46:32 GMT - Antoine Martin: owner, status changed

Can you please test r3051 to see if that helps?

(see also #307)


Thu, 11 Apr 2013 00:40:32 GMT - alas:

(I wanted to get this weirdness down while it was fresh. I will see about getting some debugging info as soon as I can.)


Mon, 15 Apr 2013 19:11:08 GMT - Antoine Martin:

r3068 prevents this race (server-side log message):

Traceback (most recent call last):
  File "/usr/lib/python2.6/site-packages/xpra/protocol.py", line 558, in do_read_parse_thread_loop
    self._process_packet_cb(self, packet)
  File "/usr/lib/python2.6/site-packages/xpra/server_base.py", line 1303, in process_packet
    assert ss.clipboard_enabled, "received a clipboard packet from a source which does not have clipboard enabled!"
AttributeError: 'NoneType' object has no attribute 'clipboard_enabled'

Which may have prevented the token from being received by the server initially. Weird, because I didn't see this error myself when I tested, only from other people's log extracts.. I think it was more likely to fire with ssh or password mode.

Confirmed, you will often find this message in the logs when this happens:

Our peer requested the contents of the clipboard, but *I* thought *they* had it... weird.

For reference, here's how I tested:


Does not work!


This can be repeated with other values with the same results.


Works


More details on what happens when we copy from the server-side (full log):

553 do_selection_clear_event(<gtk.gdk.Event at 0x7f8d7db94760: GDK_SELECTION_CLEAR selection=CLIPBOARD, target=, property=>) selection=CLIPBOARD
554 send clipboard token: CLIPBOARD
554 do_owner_changed((<gtk.Clipboard object at 0x28f3230 (GtkClipboard at 0x2955030)>, <gtk.gdk.Event at 0x7f8d7db94760: GDK_OWNER_CHANGE reason=GDK_OWNER_CHANGE_NEW_OWNER, selection=CLIPBOARD>))
555 send clipboard token: CLIPBOARD
617 process clipboard packet type=clipboard-request
617 process clipboard request, request_id=3, selection=CLIPBOARD, local name=CLIPBOARD, target=UTF8_STRING
617 get_contents(UTF8_STRING,<function got_contents at 0x292acf8>) selection=CLIPBOARD
619 unpack: <type 'NoneType'>, 0
620 unpack(..) type=UTF8_STRING, format=8, data=<type 'str'>:19
620 got_contents(UTF8_STRING, 8, <type 'str'>:19) str(data)=server-side-value3
..
621 _do_munge_raw_selection_to_wire(UTF8_STRING, UTF8_STRING, 8, <type 'str'>:19)
621 clipboard raw -> wire: ('UTF8_STRING', 8, 'server-side-value3\n') -> ('bytes', 'server-side-value3\n')
628 process clipboard packet type=clipboard-request
630 process clipboard request, request_id=4, selection=CLIPBOARD, local name=CLIPBOARD, target=UTF8_STRING
630 get_contents(UTF8_STRING,<function got_contents at 0x292a7d0>) selection=CLIPBOARD
634 unpack: <type 'NoneType'>, 0
634 unpack(..) type=UTF8_STRING, format=8, data=<type 'str'>:19
634 got_contents(UTF8_STRING, 8, <type 'str'>:19) str(data)=server-side-value3
..
634 _do_munge_raw_selection_to_wire(UTF8_STRING, UTF8_STRING, 8, <type 'str'>:19)
634 clipboard raw -> wire: ('UTF8_STRING', 8, 'server-side-value3\n') -> ('bytes', 'server-side-value3\n')
674 process clipboard packet type=clipboard-token
675 process clipboard token selection=CLIPBOARD, local clipboard name=CLIPBOARD, proxy=ClipboardProxy(CLIPBOARD)
675 got token, selection=CLIPBOARD
676 process clipboard packet type=clipboard-token
676 process clipboard token selection=CLIPBOARD, local clipboard name=CLIPBOARD, proxy=ClipboardProxy(CLIPBOARD)
676 got token, selection=CLIPBOARD
677 do_owner_changed((<gtk.Clipboard object at 0x28f3230 (GtkClipboard at 0x2955030)>, <gtk.gdk.Event at 0x7f8d7db94760: GDK_OWNER_CHANGE reason=GDK_OWNER_CHANGE_NEW_OWNER, selection=CLIPBOARD>))
678 do_owner_changed((<gtk.Clipboard object at 0x28f3230 (GtkClipboard at 0x2955030)>, <gtk.gdk.Event at 0x7f8d7db94760: GDK_OWNER_CHANGE reason=GDK_OWNER_CHANGE_NEW_OWNER, selection=CLIPBOARD>))
680 do_selection_request_event(<gtk.gdk.Event at 0x7f8d7db94760: GDK_SELECTION_REQUEST selection=CLIPBOARD, target=TARGETS, property=GDK_SELECTION>)
680 target for CLIPBOARD: 'TARGETS'
680 do_selection_request_event(<gtk.gdk.Event at 0x7f8d7db94760: GDK_SELECTION_REQUEST selection=CLIPBOARD, target=TARGETS, property=GDK_SELECTION>) target=TARGETS, selection=CLIPBOARD
681 do_selection_get(<GtkSelectionData at 0x7fffbc70ba50>, 0, 48288958) selection=CLIPBOARD
681 get clipboard from remote handler id=12
683 do_selection_request_event(<gtk.gdk.Event at 0x2890288: GDK_SELECTION_REQUEST selection=CLIPBOARD, target=TARGETS, property=GDK_SELECTION>)
683 target for CLIPBOARD: 'TARGETS'
684 do_selection_request_event(<gtk.gdk.Event at 0x2890288: GDK_SELECTION_REQUEST selection=CLIPBOARD, target=TARGETS, property=GDK_SELECTION>) target=TARGETS, selection=CLIPBOARD
684 do_selection_get(<GtkSelectionData at 0x7fffbc709230>, 0, 48288961) selection=CLIPBOARD
684 get clipboard from remote handler id=13
855 process clipboard packet type=clipboard-contents
855 process clipboard contents, selection=CLIPBOARD, type=ATOM, format=32
855 _munge_wire_selection_to_raw(atoms, ATOM, 32, <type 'tuple'>:7:['TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING', 'UTF8_STRING', 'UTF8_STRING'])
855 _munge_wire_selection_to_raw(atoms, ATOM, 32, <type 'tuple'>:7)=[<GdkAtom 0x86 = 'TIMESTAMP'>, <GdkAtom 0x89 = 'TARGETS'>, <GdkAtom 0x88 = 'MULTIPLE'>, <GdkAtom 0x47 = 'UTF8_STRING'>, <GdkAtom 0x47 = 'UTF8_STRING'>, <GdkAtom 0x47 = 'UTF8_STRING'>, <GdkAtom 0x47 = 'UTF8_STRING'>]=[134L, 137L, 136L, 71L, 71L, 71L, 71L]=['\x86', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x89', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x88', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', 'G', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', 'G', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', 'G', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', 'G', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00']
855 clipboard wire -> raw: ('ATOM', 32, 'atoms', ('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING', 'UTF8_STRING', 'UTF8_STRING')) -> '\x86\x00\x00\x00\x00\x00\x00\x00\x89\x00\x00\x00\x00\x00\x00\x00\x88\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00'
856 got clipboard contents(12)=56 (type=ATOM, format=32)
865 process clipboard packet type=clipboard-contents
866 process clipboard contents, selection=CLIPBOARD, type=ATOM, format=32
866 _munge_wire_selection_to_raw(atoms, ATOM, 32, <type 'tuple'>:7:['TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING', 'UTF8_STRING', 'UTF8_STRING'])
866 _munge_wire_selection_to_raw(atoms, ATOM, 32, <type 'tuple'>:7)=[<GdkAtom 0x86 = 'TIMESTAMP'>, <GdkAtom 0x89 = 'TARGETS'>, <GdkAtom 0x88 = 'MULTIPLE'>, <GdkAtom 0x47 = 'UTF8_STRING'>, <GdkAtom 0x47 = 'UTF8_STRING'>, <GdkAtom 0x47 = 'UTF8_STRING'>, <GdkAtom 0x47 = 'UTF8_STRING'>]=[134L, 137L, 136L, 71L, 71L, 71L, 71L]=['\x86', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x89', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x88', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', 'G', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', 'G', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', 'G', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', 'G', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00']
866 clipboard wire -> raw: ('ATOM', 32, 'atoms', ('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING', 'UTF8_STRING', 'UTF8_STRING')) -> '\x86\x00\x00\x00\x00\x00\x00\x00\x89\x00\x00\x00\x00\x00\x00\x00\x88\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00'
866 got clipboard contents(13)=56 (type=ATOM, format=32)
866 get clipboard from remote result(13)={'data': '\x86\x00\x00\x00\x00\x00\x00\x00\x89\x00\x00\x00\x00\x00\x00\x00\x88\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00', 'type': 'ATOM', 'format': 32}
867 do_selection_get(<GtkSelectionData at 0x7fffbc709230>,0,48288961) calling selection_data.set(ATOM, 32, <type 'str'>:56)
867 get clipboard from remote result(12)={'data': '\x86\x00\x00\x00\x00\x00\x00\x00\x89\x00\x00\x00\x00\x00\x00\x00\x88\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00G\x00\x00\x00\x00\x00\x00\x00', 'type': 'ATOM', 'format': 32}
867 do_selection_get(<GtkSelectionData at 0x7fffbc70ba50>,0,48288958) calling selection_data.set(ATOM, 32, <type 'str'>:56)

Same log but edited:

554 send clipboard token: CLIPBOARD
555 send clipboard token: CLIPBOARD
617 process clipboard request, request_id=3, selection=CLIPBOARD, local name=CLIPBOARD, target=UTF8_STRING
617 get_contents(UTF8_STRING,<function got_contents at 0x292acf8>) selection=CLIPBOARD
620 got_contents(UTF8_STRING, 8, <type 'str'>:19) str(data)=server-side-value3
630 process clipboard request, request_id=4, selection=CLIPBOARD, local name=CLIPBOARD, target=UTF8_STRING
630 get_contents(UTF8_STRING,<function got_contents at 0x292a7d0>) selection=CLIPBOARD
634 got_contents(UTF8_STRING, 8, <type 'str'>:19) str(data)=server-side-value3
674 process clipboard packet type=clipboard-token
675 got token, selection=CLIPBOARD
676 process clipboard packet type=clipboard-token
676 got token, selection=CLIPBOARD
680 do_selection_request_event(<gtk.gdk.Event at 0x7f8d7db94760: GDK_SELECTION_REQUEST selection=CLIPBOARD, target=TARGETS, property=GDK_SELECTION>) target=TARGETS, selection=CLIPBOARD
681 get clipboard from remote handler id=12
684 do_selection_request_event(<gtk.gdk.Event at 0x2890288: GDK_SELECTION_REQUEST selection=CLIPBOARD, target=TARGETS, property=GDK_SELECTION>) target=TARGETS, selection=CLIPBOARD
684 get clipboard from remote handler id=13
855 process clipboard packet type=clipboard-contents
855 process clipboard contents, selection=CLIPBOARD, type=ATOM, format=32
855 _munge_wire_selection_to_raw(atoms, ATOM, 32, <type 'tuple'>:7:['TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING', 'UTF8_STRING', 'UTF8_STRING'])
865 process clipboard packet type=clipboard-contents
866 process clipboard contents, selection=CLIPBOARD, type=ATOM, format=32
866 _munge_wire_selection_to_raw(atoms, ATOM, 32, <type 'tuple'>:7:['TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING', 'UTF8_STRING', 'UTF8_STRING'])
867 do_selection_get(<GtkSelectionData at 0x7fffbc709230>,0,48288961) calling selection_data.set(ATOM, 32, <type 'str'>:56)
867 do_selection_get(<GtkSelectionData at 0x7fffbc70ba50>,0,48288958) calling selection_data.set(ATOM, 32, <type 'str'>:56)

So, as soon as we claim ownership of the clipboard, we get two requests (since we send 2 tokens) for the data within a few milliseconds, and shortly after the client claims the clipboard.

Now, the client log:

141 process clipboard packet type=clipboard-token
141 remote_to_local(CLIPBOARD) local_clipboard=CLIPBOARD, remote_clipboard=CLIPBOARD
141 process clipboard token selection=CLIPBOARD, local clipboard name=CLIPBOARD, proxy=ClipboardProxy(CLIPBOARD)
141 got token, selection=CLIPBOARD
151 do_owner_changed((<gtk.Clipboard object at 0xec1490 (GtkClipboard at 0x101f090)>, <gtk.gdk.Event at 00ED4D40: GDK_OWNER_CHANGE reason=GDK_OWNER_CHANGE_NEW_OWNER, selection=CLIPBOARD>))
151 do_selection_request_event(<gtk.gdk.Event at 00ED4D40: GDK_SELECTION_REQUEST selection=CLIPBOARD, target=UTF8_STRING, property=GDK_SELECTION>)
151 target for CLIPBOARD: 'UTF8_STRING'
151 do_selection_request_event(<gtk.gdk.Event at 00ED4D40: GDK_SELECTION_REQUEST selection=CLIPBOARD, target=UTF8_STRING, property=GDK_SELECTION>) target=UTF8_STRING, selection=CLIPBOARD
151 do_selection_get(<GtkSelectionData at 0x12f050>, 0, 0) selection=CLIPBOARD
151 get clipboard from remote handler id=0
151 local_to_remote(CLIPBOARD) local_clipboard=CLIPBOARD, remote_clipboard=CLIPBOARD
151 process clipboard packet type=clipboard-token
151 remote_to_local(CLIPBOARD) local_clipboard=CLIPBOARD, remote_clipboard=CLIPBOARD
151 process clipboard token selection=CLIPBOARD, local clipboard name=CLIPBOARD, proxy=ClipboardProxy(CLIPBOARD)
151 got token, selection=CLIPBOARD
151 do_owner_changed((<gtk.Clipboard object at 0xec1490 (GtkClipboard at 0x101f090)>, <gtk.gdk.Event at 00ED4AD0: GDK_OWNER_CHANGE reason=GDK_OWNER_CHANGE_NEW_OWNER, selection=CLIPBOARD>))
151 do_selection_request_event(<gtk.gdk.Event at 00ED4AD0: GDK_SELECTION_REQUEST selection=CLIPBOARD, target=UTF8_STRING, property=GDK_SELECTION>)
151 target for CLIPBOARD: 'UTF8_STRING'
151 do_selection_request_event(<gtk.gdk.Event at 00ED4AD0: GDK_SELECTION_REQUEST selection=CLIPBOARD, target=UTF8_STRING, property=GDK_SELECTION>) target=UTF8_STRING, selection=CLIPBOARD
151 do_selection_get(<GtkSelectionData at 0x12d668>, 0, 0) selection=CLIPBOARD
151 get clipboard from remote handler id=1
151 local_to_remote(CLIPBOARD) local_clipboard=CLIPBOARD, remote_clipboard=CLIPBOARD
180 process clipboard packet type=clipboard-contents
180 process clipboard contents, selection=CLIPBOARD, type=UTF8_STRING, format=8
180 _munge_wire_selection_to_raw(bytes, UTF8_STRING, 8, <type 'str'>:19:['s', 'e', 'r', 'v', 'e', 'r', '-', 's', 'i', 'd', 'e', '-', 'v', 'a', 'l', 'u', 'e', '3', '\n'])
180 wire selection to raw, encoding=bytes, type=UTF8_STRING, format=8, len(data)=19
180 clipboard wire -> raw: ('UTF8_STRING', 8, 'bytes', 'server-side-value3\n') -> 'server-side-value3\n'
180 got clipboard contents(0)=19 (type=UTF8_STRING, format=8)
180 process clipboard packet type=clipboard-contents
180 process clipboard contents, selection=CLIPBOARD, type=UTF8_STRING, format=8
180 _munge_wire_selection_to_raw(bytes, UTF8_STRING, 8, <type 'str'>:19:['s', 'e', 'r', 'v', 'e', 'r', '-', 's', 'i', 'd', 'e', '-', 'v', 'a', 'l', 'u', 'e', '3', '\n'])
180 wire selection to raw, encoding=bytes, type=UTF8_STRING, format=8, len(data)=19
180 clipboard wire -> raw: ('UTF8_STRING', 8, 'bytes', 'server-side-value3\n') -> 'server-side-value3\n'
180 got clipboard contents(1)=19 (type=UTF8_STRING, format=8)
180 get clipboard from remote result(1)={'data': 'server-side-value3\n', 'type': 'UTF8_STRING', 'format': 8}
190 do_selection_get(<GtkSelectionData at 0x12d668>,0,0) calling selection_data.set(UTF8_STRING, 8, <type 'str'>:19)
190 do_owner_changed((<gtk.Clipboard object at 0xec1490 (GtkClipboard at 0x101f090)>, <gtk.gdk.Event at 00ED4AD0: GDK_OWNER_CHANGE reason=GDK_OWNER_CHANGE_NEW_OWNER, selection=CLIPBOARD>))
190 send clipboard token: CLIPBOARD
190 local_to_remote(CLIPBOARD) local_clipboard=CLIPBOARD, remote_clipboard=CLIPBOARD
190 get clipboard from remote result(0)={'data': 'server-side-value3\n', 'type': 'UTF8_STRING', 'format': 8}
200 do_selection_get(<GtkSelectionData at 0x12f050>,0,0) calling selection_data.set(UTF8_STRING, 8, <type 'str'>:19)
200 do_owner_changed((<gtk.Clipboard object at 0xec1490 (GtkClipboard at 0x101f090)>, <gtk.gdk.Event at 00ED4D40: GDK_OWNER_CHANGE reason=GDK_OWNER_CHANGE_NEW_OWNER, selection=CLIPBOARD>))
200 send clipboard token: CLIPBOARD
200 local_to_remote(CLIPBOARD) local_clipboard=CLIPBOARD, remote_clipboard=CLIPBOARD
290 process clipboard packet type=clipboard-pending-requests
290 process clipboard packet type=clipboard-request
290 remote_to_local(CLIPBOARD) local_clipboard=CLIPBOARD, remote_clipboard=CLIPBOARD
290 process clipboard request, request_id=23, selection=CLIPBOARD, local name=CLIPBOARD, target=TARGETS
290 get_contents(TARGETS,<function got_contents at 0x00F31CB0>) selection=CLIPBOARD
290 got_targets(<gtk.Clipboard object at 0xec1490 (GtkClipboard at 0x101f090)>, ('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING'), (None,))
290 got_contents(ATOM, 32, <type 'tuple'>:5) str(data)=('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING')..
290 _filter_targets(('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING'))=['TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING']
290 clipboard raw -> wire: ('ATOM', 32, ('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING')) -> ('atoms', ['TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING'])
290 process clipboard packet type=clipboard-pending-requests
290 process clipboard packet type=clipboard-request
290 remote_to_local(CLIPBOARD) local_clipboard=CLIPBOARD, remote_clipboard=CLIPBOARD
290 process clipboard request, request_id=24, selection=CLIPBOARD, local name=CLIPBOARD, target=TARGETS
290 get_contents(TARGETS,<function got_contents at 0x00F31CB0>) selection=CLIPBOARD
290 got_targets(<gtk.Clipboard object at 0xec1490 (GtkClipboard at 0x101f090)>, ('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING'), (None,))
290 got_contents(ATOM, 32, <type 'tuple'>:5) str(data)=('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING')..
290 _filter_targets(('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING'))=['TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING']
290 clipboard raw -> wire: ('ATOM', 32, ('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING')) -> ('atoms', ['TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING'])
480 process clipboard packet type=clipboard-pending-requests
480 process clipboard packet type=clipboard-pending-requests

Now edited:

141 process clipboard packet type=clipboard-token
151 do_selection_request_event(<gtk.gdk.Event at 00ED4D40: GDK_SELECTION_REQUEST selection=CLIPBOARD, target=UTF8_STRING, property=GDK_SELECTION>) target=UTF8_STRING, selection=CLIPBOARD
151 process clipboard packet type=clipboard-token
151 do_selection_request_event(<gtk.gdk.Event at 00ED4AD0: GDK_SELECTION_REQUEST selection=CLIPBOARD, target=UTF8_STRING, property=GDK_SELECTION>) target=UTF8_STRING, selection=CLIPBOARD
180 get clipboard from remote result(1)={'data': 'server-side-value3\n', 'type': 'UTF8_STRING', 'format': 8}
190 do_owner_changed((<gtk.Clipboard object at 0xec1490 (GtkClipboard at 0x101f090)>, <gtk.gdk.Event at 00ED4AD0: GDK_OWNER_CHANGE reason=GDK_OWNER_CHANGE_NEW_OWNER, selection=CLIPBOARD>))
190 send clipboard token: CLIPBOARD
190 get clipboard from remote result(0)={'data': 'server-side-value3\n', 'type': 'UTF8_STRING', 'format': 8}
200 do_owner_changed((<gtk.Clipboard object at 0xec1490 (GtkClipboard at 0x101f090)>, <gtk.gdk.Event at 00ED4D40: GDK_OWNER_CHANGE reason=GDK_OWNER_CHANGE_NEW_OWNER, selection=CLIPBOARD>))
200 send clipboard token: CLIPBOARD
290 got_targets(<gtk.Clipboard object at 0xec1490 (GtkClipboard at 0x101f090)>, ('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING'), (None,))
290 got_targets(<gtk.Clipboard object at 0xec1490 (GtkClipboard at 0x101f090)>, ('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'UTF8_STRING', 'UTF8_STRING'), (None,))
480 process clipboard packet type=clipboard-pending-requests
480 process clipboard packet type=clipboard-pending-requests

Thoughts:

With this patch we no longer clobber the server.


Mon, 15 Apr 2013 20:51:16 GMT - alas:

Some further notes.

Trying to use the clipboard control setter from the client tray icon.

*With the clipboard ownership set to the client - the above behavior is seen (the clipboard contents, upon a copy being made, are passed to the client clipboard & cleared from the server clipboard --> at which point those clipboard contents are no longer available on the server-side for pasting within an xpra browser).

*With the primary ownership set to the client - the server maintains the contents of the clipboard, and is thus able to paste the contents within the xpra browser --> but without those contents having been sent to the client, the contents can't be pasted client-side).

*With the primary ownership set to the client, however, a user loses the ability to select the contents of a browser address bar. Apparently the setting of the ownership to the client causes the server to try to pass the contents of the primary clipboard, as they are selected, to the client... in the process clearing the "selection" being highlighted. (This actually causes the xpra session to crash within minutes if the user tries determinedly to select the contents of the address bar.)

Some logs for that crash in case they help:

client-side

2013-04-15 12:09:35,490 Failed to load icon at C:\Program Files (x86)\Xpra\icons
\clipboard.ico: (6, 'LoadImage', 'The handle is invalid.')
2013-04-15 12:09:35,497 Failed to load icon at C:\Program Files (x86)\Xpra\icons
\clipboard.ico: (6, 'LoadImage', 'The handle is invalid.')
2013-04-15 12:09:35,505 Failed to load icon at C:\Program Files (x86)\Xpra\icons
\clipboard.ico: (6, 'LoadImage', 'The handle is invalid.')
2013-04-15 12:09:35,513 Failed to load icon at C:\Program Files (x86)\Xpra\icons
\xpra.ico: (6, 'LoadImage', 'The handle is invalid.')
pnc=: T

server-side

2013-04-15 12:09:35,782 Our peer requested the contents of the clipboard, but *I* thought *they* had it...
weird.
2013-04-15 12:09:50,909 delayed_region_timeout: sending now - something is wrong!
2013-04-15 12:10:05,981 delayed_region_timeout: sending now - something is wrong!
2013-04-15 12:10:21,050 delayed_region_timeout: sending now - something is wrong!
2013-04-15 12:10:36,262 delayed_region_timeout: sending now - something is wrong!
2013-04-15 12:10:36,308 get_backlog found some damage acks that have been pending for too long, expiring
them: [2667]
2013-04-15 12:10:38,970 Disconnecting existing client Protocol(SocketConnection(('10.0.32.196', 1200) -
('10.0.11.10', 39790))), reason is: client ping timeout, - waited 60 seconds without a response
2013-04-15 12:10:38,972 connection closed after 19651 packets received (653047 bytes) and 45864 packets sent
(76104883 bytes)
2013-04-15 12:10:38,978 xpra client disconnected.
2013-04-15 12:10:38,980 Connection lost
2013-04-15 12:10:38,987 Connection lost

*For some reason, this behavior of "pushing" the primary contents mid-selecting seems to only take place with address bar selections. (Maybe because I was using a chrome browser which was trying to process address bar contents more actively than other text?)

Perhaps, if contents of clipboard can be passed to the client without, in the process of doing so, clearing the server-side clipboard... those contents might be available both server and client side?


Tue, 16 Apr 2013 04:02:55 GMT - Antoine Martin:

without the patches from comment:26, the results from comment:27 aren't particularly useful, sorry.


Tue, 16 Apr 2013 06:29:22 GMT - Antoine Martin:

Fix committed in r3075.


Validation: with the same test setup described in comment:26 (Fedora 18 server, win32 client, gnome-terminal via xpra, notepad native win32):



(bonus check: you should be able to see the tray icon showing the clipboard whilst the transfer is in progress - see #275)



If you do find an application / test that makes this code misbehave, please try to report it in terms of reproducible "xclip" commands so we can debug it.
Testing which remote clipboard we sync to (as per comment:27) should not be a priority, and if there are issues with that let's move this to a new ticket (and we may even disable the feature) to prevent this from blocking the release.
See also #313


Wed, 17 Apr 2013 19:48:18 GMT - alas: status changed; resolution set

Ok, I can't find any way to make the clipboard misbehave between server-side xpra session browsers and the windows client (aside from some issues with our custom browser). I think this ticket is closed.


Thu, 16 May 2013 01:59:54 GMT - Antoine Martin: status changed; resolution deleted

This broke clipboard support on *nix... re-opening the ticket.

(odd because the changes were supposed to be limited to platforms that supply the "greedy" flag: win32 and osx only)


Thu, 16 May 2013 06:47:59 GMT - Antoine Martin: status changed

fixed in trunk in r3399 and 0.9.x branch in r3401

Please re-test to make sure this has not caused regressions, especially for win32 clients.


Thu, 16 May 2013 06:52:45 GMT - Antoine Martin:

Maybe the test should be:

send = (self._greedy_client and not self._block_owner_change) or (not self._greedy_client and self._have_token)

Fri, 17 May 2013 21:26:17 GMT - alas:

* Ignore this comment, it looks like the build scripts have changed in some way I can't find documented, so my build was an old 0.9.0 ... so it behaved as 0.9.0 behaves. (I'll open a ticket for that- and I'll leave you to decide whether to leave this warning for the unwary or just delete it for clarity.)


It looks like the clipboard has gone back to not capturing new copies to the clipboard within an xpra session.

Copy something in xpra client. Paste in xpra- works. Paste in client-works.

Copy something else in xpra client. Paste in xpra- works. Paste in client- pastes what was previously copied.

Copy something else again in xpra client. Paste in xpra- works. Paste in client- still pastes that same first copied data.

Copy something client-side. Paste client side- works (obviously). Paste in xpra- works.

Copy something new xpra client-side. Paste in xpra- works. Paste in client- works.

Copy something newer in xpra client-side. Paste in xpra- works. Paste in client- same new-ish (post client-copy, xpra-copy) data pastes.

As I recall, this is the behavior that takes place when the xpra copies are copied to primary and cliboard, but further copies within an xpra session only copy to primary (only to clipboard when it previously "belonged" to the client. Once it "belongs" to the xpra session then the copies are only stored in primary and the clipboard contents are unchanged from the state after that first "wrestling" of it from the client's ownership).

I'm assuming you remember that state of the clipboard behavior from previous iterations of this rabbit-hole. Let me know if you need me to do more comprehensive tests with gtk_view_clipboard and what have you (especially if you think that there might be something new in the behavior from that previous behavior).

(I should note though, that trying to build the fedora server from trunk is displaying as 0.9.0, though saying it included r3420 at the svn stage. Should the trunk be displaying as 0.9.0 or has my fedora build started pulling from some stray folder again?)


Mon, 20 May 2013 09:55:24 GMT - Antoine Martin: status changed; resolution set

the build scripts have changed in some way I can't find documented

The build scripts are kept here: browser/xpra/trunk/scripts

As for the clipboard, I've just tested on win32 and cannot make it misbehave. (but then again I was never very good at that)


Sat, 23 Jan 2021 04:50:11 GMT - migration script:

this ticket has been moved to: https://github.com/Xpra-org/xpra/issues/272