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.
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!
With a Fedora 18 server with xpra 0.9.0 and a windows client with 0.8.7 I have found the following behaviors.
In general:
Unfortunately, the behavior is just buggy enough to resist a clear understanding or predictability.
Do you have any log samples for each one?
- 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
- 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)
- 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.
- 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'?
- 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.
- 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.
- 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.
- 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:
- 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.
- 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.
- If only the primary clipboard has data, then most likely there was a recent deletion.
What is a "deletion"?
- 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?
screenshot of the new clipboard debugging tool
r2913 adds a clipboard debugging tool, and here is a screenshot:
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
CLIPBOARD
, PRIMARY
and SECONDARY
), the top line is for retrieval and the bottom one for setting.
Targets
options for retrieval starts empty, you first need to Get Targets
to obtain the list of available targets. Only then can you call Get Target
. You should probably refresh it whenever the selection owner changes, as calling Get Target
on an invalid target simply returns an empty value.
Set String
button, the data is copied from the editable field immediately, whatever text is in it at the time - changing the editable field afterwards does not have any effect until you use Set Target
or Set String
again. The only messages shown are:
Get String
), or:
Get Target
).
Set Target
button, nothing really happens yet and you can continue to type into the text field, everytime you click on Get Target
or Get String
, the value is requested and you should see a Answering selection request with value: .... The value retrieved should then be displayed. The same message is also displayed when we own the selection and an application requests the clipboard data from us.
PRIMARY
.. so clearing it will also clear the selection)
UTF8_STRING
" only and we can grab it without problems with both Get Target
and Get String
, however when we try to use Set Target
notepad++ does not seem to be aware that we offer the selection (using STRING
or UTF8_STRING
makes no difference). Using Set String
always works though.
TARGETS
", (like "TIMESTAMP
") and the application tries to display the value it retrieves (it doesn't try too hard at present - this is just to test that we do get those values)
PRIMARY
clipboard target causes it to be requested again and again (see screenshot for example). It may be a misbehaving application doing some polling, this needs testing with lighter/minimal DEs to confirm.
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.
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.
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.
primary
, so anything copied from a win client can be "pasted" (Shift-Inserted) into an xterm.
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.
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.)
primary
can be made from selecting in chrome or in xterm and are equally likely (or rather, unlikely) to be acknowledged by win client.
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.)
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.
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.
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.
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.
got token, selection=CLIPBOARD got token, selection=PRIMARY got token, selection=SECONDARY
STRING
target for CLIPBOARD
selection from the clipboard tool, with a value of "123"), this showed on the server:
do_selection_clear_event(.. GDK_SELECTION_CLEAR selection=CLIPBOARD, target=, property=>) selection=CLIPBOARD send clipboard token: CLIPBOARD process clipboard packet type=clipboard-request process clipboard request, request_id=0, selection=CLIPBOARD, local name=CLIPBOARD, target=UTF8_STRING get_contents(UTF8_STRING,<function got_contents at 0x7f2c1c85f500>) selection=CLIPBOARD unpack: <type 'NoneType'>, 0 unpack(..) type=, format=0, data=<type 'NoneType'>:0 got_contents(, 0, <type 'NoneType'>:0) str(data)=None..
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:
get_contents(TARGETS, ..)
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..
PRIMARY
is out of the question. So we remove the merged clipboard code and we have to claim ownership (send the anti-token) of the clipboard everytime we get new data to ensure that the server will send the new data when something else is copied to the clipboard. (the code is not pretty, but this was easier than subclassing or adding new signals - probably)
request_targets
- unfortunately, that doesn't fit very well with the raw-to-wire and wire-to-raw methods.. so a lot of changes to accomodate that were needed too.
CLIPBOARD
and not PRIMARY
on win32 clients since that's what most people expect.. (never mind my xterms..)
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:
do_owner_changed((<gtk.Clipboard object at 0x2a35b40 (GtkClipboard at 0x2a32820)>, \ <gtk.gdk.Event at 0x29ad260: GDK_OWNER_CHANGE \ reason=GDK_OWNER_CHANGE_NEW_OWNER, selection=CLIPBOARD>))
But this wouldn't save us much since the big waste (often transferring clipboard contents before they are needed) cannot be avoided on win32.
PRIMARY
and SECONDARY
clipboards when only win32 clients are connected. (and save wasted CPU and bandwidth)
r3039 removes the ability to select the "old" merged clipboard from the tray menu, the "merged" clipboard code no longer exists.
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:
http://www.foiledcupcake.com (all 3 clipboards) (select text in xterm) (Primary: owner changed, reason: new owner, new owner = 0x80001b) --->clipboard clear (got string selection data: '') -->primary happy happy fu (Got string selection data: ' happy happy fu') --> secondary clear (Got string selection data: '') Paste in txt happy happy fu (straight from primary)
Primary : Owner changed, reason: new owner, new owner=0x80001b ---> Clipboard clear (Got string selection data: '') --> Primary (Got string selection data: ' command not found') {Selected} --> Secondary : (Got string selection data: '')
This is as reproducible as a fecund teenager.
Primary : Owner changed, reason: new owner, new owner = 0x80001b Clipboard: (Got string selection data: '') Primary: (Got string slection data: ' virii') Secondary: (Got string selection data: '') Paste: happy happy fu (old clipboard data)
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: ''
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)
XPRA_CLIPBOARD_DEBUG=1
log samples (preferably from both sides) would help us confirm what is happening here.
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).
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.
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
Is this an update that was included on the client-side (the windows), rather than the server side? (fedora in this testing case)?
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)
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.
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}
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)
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.
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.
Can you please test r3051 to see if that helps?
(see also #307)
(I wanted to get this weirdness down while it was fresh. I will see about getting some debugging info as soon as I can.)
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:
XPRA_CLIPBOARD_DEBUG=1 xpra start :10 --bind-tcp=0.0.0.0:10000 --start-child=gnome-terminal
set XPRA_CLIPBOARD_DEBUG=1 xpra_cmd attach tcp:192.168.1.100:10000
echo server-side-value1 | xclip -i -selection clipboard
xclip -o -selection clipboard
Does not work!
This can be repeated with other values with the same results.
xclip -o -selection clipboard
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:
do_selection_clear_event
and once from do_owner_changed
... Maybe we can drop the first one?
--- src/xpra/platform/clipboard_base.py (revision 3074) +++ src/xpra/platform/clipboard_base.py (working copy) @@ -368,12 +368,15 @@ def do_selection_clear_event(self, event): # Someone else on our side has the selection debug("do_selection_clear_event(%s) selection=%s", event, self._selection) + #if send_on_owner_change, do_owner_changed will fire the token + send = (not self._send_on_owner_change or self._have_token) self._have_token = False # Emit a signal -> send a note to the other side saying "hey its # ours now" # Send off the anti-token. - self.emit("send-clipboard-token", self._selection) + if send: + self.emit("send-clipboard-token", self._selection) gtk.Invisible.do_selection_clear_event(self, event) def got_token(self):
selection_data.set
, the client claims ownership of the clipboard (and therefore clears the value on the server). And we don't want that, the _send_on_owner_change
is really a flag saying: the other may be stupid (ie: win32), send the token to force it to refresh, but the Linux servers are OK... here's a hacked patch:
### Eclipse Workspace Patch 1.0 #P Xpra Index: src/xpra/platform/clipboard_base.py =================================================================== --- src/xpra/platform/clipboard_base.py (revision 3074) +++ src/xpra/platform/clipboard_base.py (working copy) @@ -278,7 +278,8 @@ self._selection = selection self._clipboard = gtk.Clipboard(selection=selection) self._have_token = False - self._send_on_owner_change = True + import sys + self._send_on_owner_change = not sys.platform.startswith("win") self._clipboard.connect("owner-change", self.do_owner_changed) def __str__(self): @@ -390,7 +394,9 @@ + "contents of remote clipboard") def reenable_send(*args): self._send_on_owner_change = True - gobject.idle_add(reenable_send) + import sys + if not sys.platform.startswith("win"): + gobject.idle_add(reenable_send) # This function is called by the xpra core when the peer has requested the # contents of this clipboard:
With this patch we no longer clobber the server.
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?
without the patches from comment:26, the results from comment:27 aren't particularly useful, sorry.
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):
echo server-side-value1 | xclip -i -selection clipboard
xclip -o -selection clipboard
echo server-side-value2 | xclip -i -selection clipboard
(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
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.
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)
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.
Maybe the test should be:
send = (self._greedy_client and not self._block_owner_change) or (not self._greedy_client and self._have_token)
* 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?)
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)
this ticket has been moved to: https://github.com/Xpra-org/xpra/issues/272