Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clipboard client-to-server support on OSX #318

Closed
totaam opened this issue Apr 18, 2013 · 22 comments
Closed

clipboard client-to-server support on OSX #318

totaam opened this issue Apr 18, 2013 · 22 comments

Comments

@totaam
Copy link
Collaborator

totaam commented Apr 18, 2013

Issue migrated from trac ticket # 318

component: platforms | priority: minor | resolution: fixed | keywords: osx clipboard

2013-04-18 17:58:51: totaam created the issue


As of r3105, we support clipboard copy server-to-client with OSX.
To be able to support client-to-server, we would need to know when the selection owner changes so we could send the token back to the server.


Unfortunately, none of the usual GTK events fire on osx, which may be because there is no support for any of them in OSX to begin with..
[[BR]]
So we may have to resort to some native API calls, here are the pointers (mostly copied from #11 - but trimmed):

  • Manipulate Mac OS clipboard - uses Carbon.Scrap, but according to the official scrap manager documentation: The Scrap Manager is deprecated in Mac OS X version 10.5 and later. The replacement API is the Pasteboard Manager
    And in any case, there does not seem to be any way of getting notified through it.
  • The Pasteboard Reference documentation has the closest thing to a change notification mechanism: the changeCount attribute could be used via polling (yuk!).
@totaam
Copy link
Collaborator Author

totaam commented Jul 11, 2013

2013-07-11 17:37:31: antoine commented


There is no way to get asynchronous clipboard change notification, only polling! I am not the first one to be astonished by this:

Now, you would think that a simple polling loop would do the job.. But no, it's a lot more complicated than that: gtk-osx doesn't seem to like the nested main loop, etc..

In any case, here's how we could poll the changeCount:

import AppKit.NSPasteboard      #@UnresolvedImport
self.pasteboard = AppKit.NSPasteboard.generalPasteboard()
count = self.pasteboard.changeCount()

@totaam
Copy link
Collaborator Author

totaam commented Sep 19, 2013

2013-09-19 23:32:28: afarr commented


Will it be of any use/utility to have clipboard test data for this, server/client? (Is there an osx version of gtk_keyboard_test? I seem to remember the /lib/python2.7/xpra path in the linux server xpra, but no sign of anything there in mac client...)

@totaam
Copy link
Collaborator Author

totaam commented Oct 14, 2013

2013-10-14 14:59:52: totaam commented


Will it be of any use/utility to have clipboard test data for this, server/client?
Not really, the OSX API is incomplete, so there is no data to look at!

Is there an osx version of gtk_keyboard_test?
Yes with r4492 it is now bundled in the disk image so you can run it like so (assuming you have a terminal in the directory containing Xpra.app):

Xpra.app/Contents/Helpers/Python 

With previous versions, the file gtk_view_clipboard.py was not bundled in the xpra disk image, so in that case you have to [/browser/xpra/trunk/src/xpra/gtk_common/gtk_view_clipboard.py download it] first.

(this is just for reference, I don't think using the tool is going to help us much unfortunately..)


I've added most of what is needed in r4490, refactoring the ugly UI thread loop code in the process so we can re-use its thread and loop rather than adding yet another thread for doing the clipboard polling.
r4491 also increases the frequency of the polling loop to run every 500ms, which is a little bit too fast for my liking, but should ensure that the clipboard contents are synced fast enough in most cases (average case will be 250ms).
I can copy from the client to the server, and it's quite hard to manage to fire the paste server side before the osx clipboard contents have been synced.

Sadly, I cannot copy from server to client (anymore?), I've tried going back to 0.10.x and I have the same problem there. I am pretty sure that it used to work though, I had tested the code in r3105... Can you help me figure out if this ever worked, with which versions/builds?

@totaam
Copy link
Collaborator Author

totaam commented Oct 19, 2013

2013-10-19 15:32:18: totaam uploaded file osx-clipboard.patch (10.6 KiB)

this patch makes the clipboard work in both directions but crashes the server in some cases!

@totaam
Copy link
Collaborator Author

totaam commented Oct 19, 2013

2013-10-19 15:42:00: totaam commented


The patch above makes the server crash simply by coping some text with gedit, seemingly because of what we set the TARGET to (ATOMs) in do_selection_get.

Server log shows:

2013-10-19 21:33:16,581 do_selection_clear_event(<gtk.gdk.Event at 0x2e9fa80: GDK_SELECTION_CLEAR selection=CLIPBOARD, target=, property=>) have_token=True, block_owner_change=False selection=CLIPBOARD
2013-10-19 21:33:16,581 send clipboard token: CLIPBOARD
2013-10-19 21:33:16,581 get_contents(TARGETS,<function got_targets at 0x3c291b8>) selection=CLIPBOARD
2013-10-19 21:33:16,581 do_owner_changed((<gtk.Clipboard object at 0x167c0f0 (GtkClipboard at 0x1701f00)>, <gtk.gdk.Event at 0x1c5aa80: GDK_OWNER_CHANGE reason=GDK_OWNER_CHANGE_NEW_OWNER, selection=CLIPBOARD>)) greedy_client=True, block_owner_change=False
2013-10-19 21:33:16,582 send clipboard token: CLIPBOARD
2013-10-19 21:33:16,582 get_contents(TARGETS,<function got_targets at 0x3c29320>) selection=CLIPBOARD
2013-10-19 21:33:16,595 got_targets(<gtk.Clipboard object at 0x167c0f0 (GtkClipboard at 0x1701f00)>, ('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'SAVE_TARGETS', 'GTK_TEXT_BUFFER_CONTENTS', 'application/x-gtk-text-buffer-rich-text', 'UTF8_STRING', 'COMPOUND_TEXT', 'TEXT', 'STRING', 'text/plain;charset=utf-8', 'text/plain'), (None,))
2013-10-19 21:33:16,595 got_targets for selection CLIPBOARD: ATOM, 32, ('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'SAVE_TARGETS', 'GTK_TEXT_BUFFER_CONTENTS', 'application/x-gtk-text-buffer-rich-text', 'UTF8_STRING', 'COMPOUND_TEXT', 'TEXT', 'STRING', 'text/plain;charset=utf-8', 'text/plain')
2013-10-19 21:33:16,595 get_contents(UTF8_STRING,<function got_contents at 0x3c292a8>) selection=CLIPBOARD
2013-10-19 21:33:16,597 got_targets(<gtk.Clipboard object at 0x167c0f0 (GtkClipboard at 0x1701f00)>, ('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'SAVE_TARGETS', 'GTK_TEXT_BUFFER_CONTENTS', 'application/x-gtk-text-buffer-rich-text', 'UTF8_STRING', 'COMPOUND_TEXT', 'TEXT', 'STRING', 'text/plain;charset=utf-8', 'text/plain'), (None,))
2013-10-19 21:33:16,598 got_targets for selection CLIPBOARD: ATOM, 32, ('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'SAVE_TARGETS', 'GTK_TEXT_BUFFER_CONTENTS', 'application/x-gtk-text-buffer-rich-text', 'UTF8_STRING', 'COMPOUND_TEXT', 'TEXT', 'STRING', 'text/plain;charset=utf-8', 'text/plain')
2013-10-19 21:33:16,598 get_contents(UTF8_STRING,<function got_contents at 0x3c291b8>) selection=CLIPBOARD
2013-10-19 21:33:16,600 unpack <gtk.Clipboard object at 0x167c0f0 (GtkClipboard at 0x1701f00)>: <type 'gtk.SelectionData'>
2013-10-19 21:33:16,600 unpack: <GtkSelectionData at 0x19b6140>
2013-10-19 21:33:16,601 unpack(..) type=UTF8_STRING, format=8, data=<type 'str'>:11
2013-10-19 21:33:16,601 got_contents for selection CLIPBOARD: UTF8_STRING, 8, hello-world
2013-10-19 21:33:16,601 _do_munge_raw_selection_to_wire(UTF8_STRING, UTF8_STRING, 8, <type 'str'>:11)
2013-10-19 21:33:16,602 sending token with target data: {'UTF8_STRING': ('UTF8_STRING', 8, 'bytes', 'hello-world')}
2013-10-19 21:33:16,610 unpack <gtk.Clipboard object at 0x167c0f0 (GtkClipboard at 0x1701f00)>: <type 'gtk.SelectionData'>
2013-10-19 21:33:16,611 unpack: <GtkSelectionData at 0x19b6180>
2013-10-19 21:33:16,611 unpack(..) type=UTF8_STRING, format=8, data=<type 'str'>:11
2013-10-19 21:33:16,611 got_contents for selection CLIPBOARD: UTF8_STRING, 8, hello-world
2013-10-19 21:33:16,612 _do_munge_raw_selection_to_wire(UTF8_STRING, UTF8_STRING, 8, <type 'str'>:11)
2013-10-19 21:33:16,612 sending token with target data: {'UTF8_STRING': ('UTF8_STRING', 8, 'bytes', 'hello-world')}
2013-10-19 21:33:16,644 process clipboard packet type=clipboard-token
2013-10-19 21:33:16,644 process clipboard token selection=CLIPBOARD, local clipboard name=CLIPBOARD, proxy=ClipboardProxy(CLIPBOARD)
2013-10-19 21:33:16,644 got token, selection=CLIPBOARD, targets=None, target_data=None
2013-10-19 21:33:16,644 do_owner_changed((<gtk.Clipboard object at 0x167c0f0 (GtkClipboard at 0x1701f00)>, <gtk.gdk.Event at 0x1c5aa80: GDK_OWNER_CHANGE reason=GDK_OWNER_CHANGE_NEW_OWNER, selection=CLIPBOARD>)) greedy_client=True, block_owner_change=True
2013-10-19 21:33:16,644 process clipboard packet type=clipboard-token
2013-10-19 21:33:16,645 process clipboard token selection=CLIPBOARD, local clipboard name=CLIPBOARD, proxy=ClipboardProxy(CLIPBOARD)
2013-10-19 21:33:16,645 got token, selection=CLIPBOARD, targets=None, target_data=None
2013-10-19 21:33:16,645 do_owner_changed((<gtk.Clipboard object at 0x167c0f0 (GtkClipboard at 0x1701f00)>, <gtk.gdk.Event at 0x1c5aa80: GDK_OWNER_CHANGE reason=GDK_OWNER_CHANGE_NEW_OWNER, selection=CLIPBOARD>)) greedy_client=True, block_owner_change=False
2013-10-19 21:33:16,645 send clipboard token: CLIPBOARD
2013-10-19 21:33:16,645 get_contents(TARGETS,<function got_targets at 0x3c291b8>) selection=CLIPBOARD
2013-10-19 21:33:16,645 do_selection_get(<GtkSelectionData at 0x7fffb7a66dc0>, 0, 39616166) selection=CLIPBOARD
2013-10-19 21:33:16,645 get clipboard from remote handler id=4
2013-10-19 21:33:16,646 do_selection_request_event(<gtk.gdk.Event at 0x16299b8: GDK_SELECTION_REQUEST selection=CLIPBOARD, target=TARGETS, property=GDK_SELECTION>)
2013-10-19 21:33:16,646 target for CLIPBOARD: 'TARGETS'
2013-10-19 21:33:16,647 do_selection_request_event(<gtk.gdk.Event at 0x16299b8: GDK_SELECTION_REQUEST selection=CLIPBOARD, target=TARGETS, property=GDK_SELECTION>) target=TARGETS, selection=CLIPBOARD
2013-10-19 21:33:16,647 do_selection_get(<GtkSelectionData at 0x7fffb7a64ad0>, 0, 39616167) selection=CLIPBOARD
2013-10-19 21:33:16,647 get clipboard from remote handler id=5
2013-10-19 21:33:16,647 do_selection_request_event(<gtk.gdk.Event at 0x1629940: GDK_SELECTION_REQUEST selection=CLIPBOARD, target=TARGETS, property=GDK_SELECTION>)
2013-10-19 21:33:16,647 target for CLIPBOARD: 'TARGETS'
2013-10-19 21:33:16,647 do_selection_request_event(<gtk.gdk.Event at 0x1629940: GDK_SELECTION_REQUEST selection=CLIPBOARD, target=TARGETS, property=GDK_SELECTION>) target=TARGETS, selection=CLIPBOARD
2013-10-19 21:33:16,647 do_selection_get(<GtkSelectionData at 0x7fffb7a627a0>, 0, 39616167) selection=CLIPBOARD
2013-10-19 21:33:16,647 get clipboard from remote handler id=6
2013-10-19 21:33:16,674 process clipboard packet type=clipboard-contents
2013-10-19 21:33:16,675 process clipboard contents, selection=CLIPBOARD, type=ATOM, format=32
2013-10-19 21:33:16,675 _munge_wire_selection_to_raw(atoms, ATOM, 32, <type 'tuple'>:2:['UTF8_STRING', 'public.utf8-plain-text'])
2013-10-19 21:33:16,675 _munge_wire_selection_to_raw(atoms, ATOM, 32, <type 'tuple'>:2)=[<GdkAtom 0x47 # 'UTF8_STRING'>, <GdkAtom 0xa5'public.utf8-plain-text'>]=[71L, 165L]=['G', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\xa5', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00']
2013-10-19 21:33:16,675 clipboard wire -> raw: ('ATOM', 32, 'atoms', ('UTF8_STRING', 'public.utf8-plain-text')) -> 'G\x00\x00\x00\x00\x00\x00\x00\xa5\x00\x00\x00\x00\x00\x00\x00'
2013-10-19 21:33:16,676 got clipboard contents for id=4 len=16, loop=<xpra.gtk_common.nested_main.NestedMainLoop object at 0x4aa7cd0> (type=ATOM, format=32)
2013-10-19 21:33:16,714 process clipboard packet type=clipboard-contents
2013-10-19 21:33:16,714 process clipboard contents, selection=CLIPBOARD, type=ATOM, format=32
2013-10-19 21:33:16,714 _munge_wire_selection_to_raw(atoms, ATOM, 32, <type 'tuple'>:2:['UTF8_STRING', 'public.utf8-plain-text'])
2013-10-19 21:33:16,715 _munge_wire_selection_to_raw(atoms, ATOM, 32, <type 'tuple'>:2)=[<GdkAtom 0x47 # 'UTF8_STRING'>, <GdkAtom 0xa5'public.utf8-plain-text'>]=[71L, 165L]=['G', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\xa5', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00']
2013-10-19 21:33:16,715 clipboard wire -> raw: ('ATOM', 32, 'atoms', ('UTF8_STRING', 'public.utf8-plain-text')) -> 'G\x00\x00\x00\x00\x00\x00\x00\xa5\x00\x00\x00\x00\x00\x00\x00'
2013-10-19 21:33:16,715 got clipboard contents for id=5 len=16, loop=<xpra.gtk_common.nested_main.NestedMainLoop object at 0x4aa7d10> (type=ATOM, format=32)
2013-10-19 21:33:16,715 process clipboard packet type=clipboard-contents
2013-10-19 21:33:16,715 process clipboard contents, selection=CLIPBOARD, type=ATOM, format=32
2013-10-19 21:33:16,715 _munge_wire_selection_to_raw(atoms, ATOM, 32, <type 'tuple'>:2:['UTF8_STRING', 'public.utf8-plain-text'])
2013-10-19 21:33:16,715 _munge_wire_selection_to_raw(atoms, ATOM, 32, <type 'tuple'>:2)=[<GdkAtom 0x47 # 'UTF8_STRING'>, <GdkAtom 0xa5'public.utf8-plain-text'>]=[71L, 165L]=['G', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\xa5', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00']
2013-10-19 21:33:16,716 clipboard wire -> raw: ('ATOM', 32, 'atoms', ('UTF8_STRING', 'public.utf8-plain-text')) -> 'G\x00\x00\x00\x00\x00\x00\x00\xa5\x00\x00\x00\x00\x00\x00\x00'
2013-10-19 21:33:16,716 got clipboard contents for id=6 len=16, loop=<xpra.gtk_common.nested_main.NestedMainLoop object at 0x4aa78d0> (type=ATOM, format=32)
2013-10-19 21:33:16,716 get clipboard from remote result(6)={'data': 'G\x00\x00\x00\x00\x00\x00\x00\xa5\x00\x00\x00\x00\x00\x00\x00', 'type': 'ATOM', 'format': 32}
2013-10-19 21:33:16,716 do_selection_get(<GtkSelectionData at 0x7fffb7a627a0>,0,39616167) calling selection_data.set(ATOM, 32, <type 'str'>:16)
2013-10-19 21:33:16,717 get clipboard from remote result(5)={'data': 'G\x00\x00\x00\x00\x00\x00\x00\xa5\x00\x00\x00\x00\x00\x00\x00', 'type': 'ATOM', 'format': 32}
2013-10-19 21:33:16,718 do_selection_get(<GtkSelectionData at 0x7fffb7a64ad0>,0,39616167) calling selection_data.set(ATOM, 32, <type 'str'>:16)
2013-10-19 21:33:16,719 get clipboard from remote result(4)={'data': 'G\x00\x00\x00\x00\x00\x00\x00\xa5\x00\x00\x00\x00\x00\x00\x00', 'type': 'ATOM', 'format': 32}
2013-10-19 21:33:16,719 do_selection_get(<GtkSelectionData at 0x7fffb7a66dc0>,0,39616166) calling selection_data.set(ATOM, 32, <type 'str'>:16)
2013-10-19 21:33:16,719 got_targets(<gtk.Clipboard object at 0x167c0f0 (GtkClipboard at 0x1701f00)>, ('UTF8_STRING', 'public.utf8-plain-text'), (None,))
2013-10-19 21:33:16,720 got_targets for selection CLIPBOARD: ATOM, 32, ('UTF8_STRING', 'public.utf8-plain-text')
2013-10-19 21:33:16,720 get_contents(UTF8_STRING,<function got_contents at 0x3c290c8>) selection=CLIPBOARD
2013-10-19 21:33:16,720 unpack <gtk.Clipboard object at 0x167c0f0 (GtkClipboard at 0x1701f00)>: <type 'gtk.SelectionData'>
2013-10-19 21:33:16,720 unpack: <GtkSelectionData at 0x19b61c0>

Which can be summarized as:

do_selection_clear_event -> get targets -> got targets -> get contents (UTF8_STRING) -> unpack -> got contents -> munge -> sending token with target data

And repeated as we fire the same sequence of events after a do_owner_changed. (needs blocking)
[[BR]]
The client sends the token back immediately (needs blocking - we should ignore the contents we have just set, sadly the changecount seems to increase after we set the contents?):

clipboard-token -> do_selection_request_event (TARGETS) -> do_selection_get -> get clipboard from remote handler

We request the TARGETS (three times?) and blow up on:

got contents -> do_selection_get -> selection_data.set (xxx) -> got_targets -> got_contents -> unpack

And gdb gives us this beautiful backtrace:

(gdb) bt
#0  0x0000003934b39bcf in __strlen_sse42 () from /lib64/libc.so.6
#1  0x0000003def495cf0 in PyString_FromString () from /lib64/libpython2.7.so.1.0
#2  0x00007f54c99cf6de in _wrap_gtk_selection_data__get_type ()
   from /usr/lib64/python2.7/site-packages/gtk-2.0/gtk/_gtk.so
#3  0x0000003def45e830 in ?? () from /lib64/libpython2.7.so.1.0
#4  0x0000003def4847e1 in _PyObject_GenericGetAttrWithDict () from /lib64/libpython2.7.so.1.0
#5  0x0000003def4da839 in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#6  0x0000003def4dec7d in PyEval_EvalCodeEx () from /lib64/libpython2.7.so.1.0
#7  0x0000003def46dca0 in ?? () from /lib64/libpython2.7.so.1.0
#8  0x0000003def449dd3 in PyObject_Call () from /lib64/libpython2.7.so.1.0
#9  0x0000003def4d8af7 in PyEval_CallObjectWithKeywords () from /lib64/libpython2.7.so.1.0
#10 0x00007f54c99e75fb in clipboard_request_contents_cb () from /usr/lib64/python2.7/site-packages/gtk-2.0/gtk/_gtk.so
#11 0x00000039a5683710 in selection_received () from /lib64/libgtk-x11-2.0.so.0
#12 0x000000393860f9a2 in g_closure_invoke () from /lib64/libgobject-2.0.so.0
#13 0x0000003938620a3d in signal_emit_unlocked_R () from /lib64/libgobject-2.0.so.0
#14 0x0000003938628829 in g_signal_emit_valist () from /lib64/libgobject-2.0.so.0
#15 0x0000003938628fa2 in g_signal_emit_by_name () from /lib64/libgobject-2.0.so.0
#16 0x00000039a55ad343 in gtk_selection_retrieval_report () from /lib64/libgtk-x11-2.0.so.0
#17 0x00000039a55aedb8 in gtk_selection_convert () from /lib64/libgtk-x11-2.0.so.0
#18 0x00007f54c99e7e5f in _wrap_gtk_clipboard_request_contents ()
   from /usr/lib64/python2.7/site-packages/gtk-2.0/gtk/_gtk.so
#19 0x0000003def4ddcee in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#20 0x0000003def4dec7d in PyEval_EvalCodeEx () from /lib64/libpython2.7.so.1.0
#21 0x0000003def4dd769 in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#22 0x0000003def4dec7d in PyEval_EvalCodeEx () from /lib64/libpython2.7.so.1.0
#23 0x0000003def4dd769 in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#24 0x0000003def4dec7d in PyEval_EvalCodeEx () from /lib64/libpython2.7.so.1.0
#25 0x0000003def46dca0 in ?? () from /lib64/libpython2.7.so.1.0
#26 0x0000003def449dd3 in PyObject_Call () from /lib64/libpython2.7.so.1.0
#27 0x0000003def4d8af7 in PyEval_CallObjectWithKeywords () from /lib64/libpython2.7.so.1.0
#28 0x00007f54c99d1175 in clipboard_request_targets_cb () from /usr/lib64/python2.7/site-packages/gtk-2.0/gtk/_gtk.so
#29 0x00000039a5683511 in request_targets_received_func () from /lib64/libgtk-x11-2.0.so.0
#30 0x00000039a5683710 in selection_received () from /lib64/libgtk-x11-2.0.so.0
#31 0x000000393860fa28 in g_closure_invoke () from /lib64/libgobject-2.0.so.0
#32 0x0000003938620a3d in signal_emit_unlocked_R () from /lib64/libgobject-2.0.so.0
#33 0x0000003938628829 in g_signal_emit_valist () from /lib64/libgobject-2.0.so.0
#34 0x0000003938628fa2 in g_signal_emit_by_name () from /lib64/libgobject-2.0.so.0
#35 0x00000039a55ad343 in gtk_selection_retrieval_report () from /lib64/libgtk-x11-2.0.so.0
#36 0x00000039a55aedb8 in gtk_selection_convert () from /lib64/libgtk-x11-2.0.so.0
#37 0x00007f54c99e7cae in _wrap_gtk_clipboard_request_targets ()
   from /usr/lib64/python2.7/site-packages/gtk-2.0/gtk/_gtk.so
#38 0x0000003def4ddcee in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#39 0x0000003def4dec7d in PyEval_EvalCodeEx () from /lib64/libpython2.7.so.1.0
#40 0x0000003def4dd769 in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#41 0x0000003def4dec7d in PyEval_EvalCodeEx () from /lib64/libpython2.7.so.1.0
#42 0x0000003def46dca0 in ?? () from /lib64/libpython2.7.so.1.0
#43 0x0000003def449dd3 in PyObject_Call () from /lib64/libpython2.7.so.1.0
#44 0x0000003def458555 in ?? () from /lib64/libpython2.7.so.1.0
#45 0x0000003def449dd3 in PyObject_Call () from /lib64/libpython2.7.so.1.0
#46 0x0000003def4d8af7 in PyEval_CallObjectWithKeywords () from /lib64/libpython2.7.so.1.0
#47 0x00007f54c9dd7e59 in pyg_closure_marshal () from /usr/lib64/python2.7/site-packages/gobject/_gobject.so
#48 0x000000393860fa28 in g_closure_invoke () from /lib64/libgobject-2.0.so.0
#49 0x0000003938620a3d in signal_emit_unlocked_R () from /lib64/libgobject-2.0.so.0
#50 0x00000039386278d1 in g_signal_emitv () from /lib64/libgobject-2.0.so.0
#51 0x00007f54c9dd12cc in pygobject_emit () from /usr/lib64/python2.7/site-packages/gobject/_gobject.so
#52 0x0000003def4ddcee in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#53 0x0000003def4dec7d in PyEval_EvalCodeEx () from /lib64/libpython2.7.so.1.0
#54 0x0000003def46dca0 in ?? () from /lib64/libpython2.7.so.1.0
#55 0x0000003def449dd3 in PyObject_Call () from /lib64/libpython2.7.so.1.0
#56 0x0000003def458555 in ?? () from /lib64/libpython2.7.so.1.0
#57 0x0000003def449dd3 in PyObject_Call () from /lib64/libpython2.7.so.1.0
#58 0x0000003def4d8af7 in PyEval_CallObjectWithKeywords () from /lib64/libpython2.7.so.1.0
#59 0x00007f54c9dd7e59 in pyg_closure_marshal () from /usr/lib64/python2.7/site-packages/gobject/_gobject.so
#60 0x000000393860fa28 in g_closure_invoke () from /lib64/libgobject-2.0.so.0
#61 0x0000003938620a3d in signal_emit_unlocked_R () from /lib64/libgobject-2.0.so.0
#62 0x0000003938628829 in g_signal_emit_valist () from /lib64/libgobject-2.0.so.0
#63 0x0000003938628a72 in g_signal_emit () from /lib64/libgobject-2.0.so.0
#64 0x00000039a5540d9d in gtk_main_do_event () from /lib64/libgtk-x11-2.0.so.0
#65 0x00000039a5c5e2dc in gdk_event_dispatch () from /lib64/libgdk-x11-2.0.so.0
#66 0x0000003936e47e06 in g_main_context_dispatch () from /lib64/libglib-2.0.so.0
#67 0x0000003936e48158 in g_main_context_iterate.isra.22 () from /lib64/libglib-2.0.so.0
#68 0x0000003936e4855a in g_main_loop_run () from /lib64/libglib-2.0.so.0
#69 0x00000039a553fdb7 in gtk_main () from /lib64/libgtk-x11-2.0.so.0

Better summarized as:

__strlen_sse42 ()
PyString_FromString ()
_wrap_gtk_selection_data__get_type ()
clipboard_request_contents_cb ()
selection_received ()
gtk_selection_retrieval_report ()
gtk_selection_convert ()
_wrap_gtk_clipboard_request_contents ()
clipboard_request_targets_cb ()
request_targets_received_func ()
selection_received ()
gtk_selection_retrieval_report ()
gtk_selection_convert ()
_wrap_gtk_clipboard_request_targets ()
signal_emit_unlocked_R ()
gtk_main ()

When we unpack, we print the selection_data.type and that seems to trigger the crash.

@totaam
Copy link
Collaborator Author

totaam commented Oct 20, 2013

2013-10-20 10:00:44: totaam commented


That was HARD, GTK on OSX does not support nested main loops... so we have to be careful not to use them.

The relevant changes are in:

  • r4570 adds debugging to the nested main loop, useful if the server gets stuck:
XPRA_NESTED_DEBUG=1 xpra start ...
  • r4571 is a typo which will be backported to v0.10.x
  • r4572 is a preparatory refactoring
  • r4573 is the actual OSX fix (see commit message for details)
  • r4577 avoids making unnecessary clipboard requests for platforms that do not support more than one clipboard (ie: OSX and win32 do not use PRIMARY and SECONDARY selections)
  • r4576 makes it easier to trigger error conditions (failure to reply)

[[BR]]

Please test thoroughly, I had seen an instance of the server getting stuck in the nested main loop (see XPRA_NESTED_DEBUG above) but I have not been able to reproduce it since despite adding code to try to trigger the same problem (r4576).
In particular:

  • copy client to server, and again (different data), then the other way (server to client), and again..
  • testing with xclip in and out
  • testing with gedit to OSX client
  • testing odd clipboard formats (not sure which apps are weirder - OSX client application formats are pretty weird, but client to server is less of an issue)
  • connecting with an OSX client, then with a win32 client (to the same session) then with a Linux client (and verify that the Linux client can still access PRIMARY and SECONDARY selections)
  • osx and win32 clients should see no clipboard traffic (enable with XPRA_CLIPBOARD_DEBUG=1) when PRIMARY and SECONDARY get modidied server side

@totaam
Copy link
Collaborator Author

totaam commented Oct 22, 2013

2013-10-22 21:19:38: afarr commented


Using osx xpra 0.10.8 4595 client-side and 0.10.8-1.fc19.x86_64.rpm server-side the clipboard seems to be behaving exactly as I recall it behaving before.

Copying from local desktop and pasting to the xpra session works repeatedly as expected.

Copying within the xpra session produces the following message in the client-side terminal on the first attempt:

Users/alex/Desktop/xpra.app/Contents/Resources/lib/python/xpra/clipboard/clipboard_base.py:522: Warning: gsignal.c:3320: value location for `gboolean' passed as NULL
2013-10-22 12:54:24,702 unhandled format 0 for clipboard data type NONE

The second and subsequent attempts to copy within the xpra session produces the following (shorter) message in client-side terminal:

unhandled format 0 for clipboard data type NONE

Nothing copied within the xpra session was able to be pasted either within the xpra session or to the local desktop applications.

The first (failed) paste attempt produced the following message in client-side terminal:

/Users/alex/Desktop/xpra.app/Contents/Resources/lib/python/xpra/clipboard/clipboard_base.py:522: Warning: gsignal.c:3320: value location for `gboolean' passed as NULL
2013-10-22 12:54:24,702 unhandled format 0 for clipboard data type NONE

All subsequent (failed) paste attempts produce the same output message as the copy attempts, though usually significantly more than one line:

2013-10-22 12:55:21,800 unhandled format 0 for clipboard data type NONE
2013-10-22 12:55:21,851 unhandled format 0 for clipboard data type NONE
2013-10-22 12:55:21,924 unhandled format 0 for clipboard data type NONE

I couldn't find any sign of correlation of the number of iterations of the output message with the length or other composition aspects of the (expected) contents of the clipboard, however.

@totaam
Copy link
Collaborator Author

totaam commented Oct 23, 2013

2013-10-23 01:31:45: totaam commented


That's because the 0.10.x stable branch does not, and more than likely will not, contain those intrusive changes.

Please try trunk.

@totaam
Copy link
Collaborator Author

totaam commented Oct 23, 2013

2013-10-23 04:47:01: totaam commented


Updated beta builds for most platforms are in the beta area (inc win32, osx and rpms, no debs)

@totaam
Copy link
Collaborator Author

totaam commented Oct 23, 2013

2013-10-23 23:17:45: afarr commented


Currently the only osx builds I see in http://xpra.org/beta/osx/x86/ are the 0.11.0 [r4592](../commit/f568354a706dfc929f8c6c940a57d83f4828952d) (which produces results as above) and the xpra.dmg with a date of 10/17 which, when installed, shows 0.11.0 [r4542](../commit/e38025ada855e0cae490a5023bd87f36667c3d4e) in the info tab and which, also, produces the results above when the clipboard is tested.

Going into the xpra.org/dists/osx/x86/ directory I find an xpra.dmg which is dated 22-Oct and which shows as xpra 0.10.8 4595 when installed and the info is checked.

Testing with that build I was able to copy within the xpra session and paste somewhere else within the xpra session successfully, but only once. A second attempt to copy and paste failed (clipboard was apparently cleared, as nothing pasted) and, once again, produced the unhandled format error as above.

Copying from local desktop and pasting to the xpra session works consistently.

Copying something from the local desktop & successfully pasting to the xpra session, followed by copying from the xpra session and trying to paste to the local desktop (.txt file) outputs nothing, so the copy attempt within the xpra is interacting with, and apparently clearing, the clipboard.

Oddly, disconnecting the client from the server, then re-connecting, does not enable a new & successful single copying and pasting, neither with the clipboard used while the client is disconnected nor with the clipboard not used while disconnected. (In other words, I was able to copy once, and only once. Inexplicably, neither restarting client nor both server and client allowed me to copy & paste successfully within xpra session a second time.)

@totaam
Copy link
Collaborator Author

totaam commented Oct 24, 2013

2013-10-24 01:38:17: totaam commented


The last beta is indeed 0.11.0-[r4592](../commit/f568354a706dfc929f8c6c940a57d83f4828952d) which is dated yesterday.
If this does not allow you to copy, your server is probably not up to date.

As per comment:8, there is no point in testing the 0.10.x branch which does not and will not have the code in it.

Each directory contains an "Xpra.dmg" symlink for people to download directly. You can see it is the same file as the latest release in that directory as it has the same size and time.
(sadly, apache does not show us that it is a symlink)

@totaam
Copy link
Collaborator Author

totaam commented Oct 24, 2013

2013-10-24 21:44:58: afarr commented


Ok, now that I've gotten hold of the right build to test, I have to applaud your work.

Works as expected in both directions. Works as expected with xclip (once I figured out how that tool worked) and with gedit. Works when swapped back and forth with a windows to osx client. (I don't have a handy linux machine to test on I'm afraid.)

A few notes though.

First whenever copying on the local desktop the Xpra icon "hopped" in the dock (oddly, only before the session was swapped back and forth with the windows client).

Second, whenever pasting into the xpra session I continue to get the warning:
2013-10-24 13:40:08,059 unhandled format 0 for clipboard data type NONE - the clipboard works as expected though.

Finally, whenever copying locally while clipboard has a value previously copied from within an xpra session, I get the following warning:
Xpra[10085:3203] *** __NSAutoreleaseNoPool(): Object 0x1d1c90b0 of class __NSFastEnumerationEnumerator autoreleased with no pool in place - just leaking - again though, the clipboard behaves as expected.

I doubt the warnings are important, but I thought they might be interesting to note.

@totaam
Copy link
Collaborator Author

totaam commented Oct 25, 2013

2013-10-25 02:20:46: totaam commented


Works as expected with xclip (once I figured out how that tool worked)
[[BR]]
Using xclip is documented here: Clipboard

[[BR]]

whenever copying on the local desktop the Xpra icon "hopped" in the dock
[[BR]]
This is #275 - assigned to afarr for 7 months.. ;)

[[BR]]

only before the session was swapped back and forth with the windows client
[[BR]]
Are you saying that the dock icon does not bounce after re-connecting?
It should. Re-connecting should not make any difference.
The problem with this bouncing dock feature on OSX is that the clipboard is now synchronous in the server-to-client direction, so a little redundant in that case. (probably still useful for client-to-server direction)

[[BR]]


Finally, those warnings:

unhandled format 0 for clipboard data type NONE
__NSAutoreleaseNoPool(): Object 0x1d1c90b0 of class __NSFastEnumerationEnumerator autoreleased with no pool in place - just leaking

Will need to be investigated to make sure we aren't leaking memory. They're in gtk-osx code, not xpra's.

[[BR]]

Works as expected in both directions.
[[BR]]
Good, will close this ticket once the warnings are investigated.
Please re-assign to me after answering the question above - (and assuming my answers make sense).

@totaam
Copy link
Collaborator Author

totaam commented Oct 26, 2013

2013-10-26 02:54:57: afarr commented


I tested again, xpra 0.11.0 r4592, again... with an osx 10.6.8 machine, the xpra icon did indeed stop bouncing after reconnecting.

Oddly, with an osx 10.7.5 machine the icon didn't bounce at all, but instead displayed the keyboard icon referred to in #275.

(In our particular case, odd 10.6.8 behavior is not an issue. If you would like me to further test I'd be interested to hear what you think I should look for. I saw no output to suggest why it would be behaving differently after re-connecting than before.)

@totaam
Copy link
Collaborator Author

totaam commented Oct 29, 2013

2013-10-29 13:38:52: totaam commented


Closing, will follow up in #275 which is the right ticket for the "bouncing clipboard notification" feature.

FYI: there was some confusion over "re-connecting" I think. I thought that you meant that the "bouncing" only occurred on the first connection and not subsequent ones, but I now think that you meant that re-connecting stopped the bouncing if it was already happening - not that it prevented new bouncing from happening once re-connected. Right? (please add to #275, bouncing should occur - though not for very long, maybe not long enough to notice... in which case the logging is the only way to know for sure)

Looks done, closing.

@totaam
Copy link
Collaborator Author

totaam commented Oct 29, 2013

2013-10-29 13:39:31: totaam changed status from new to closed

@totaam
Copy link
Collaborator Author

totaam commented Oct 29, 2013

2013-10-29 13:39:31: totaam changed resolution from ** to fixed

@totaam
Copy link
Collaborator Author

totaam commented Jul 14, 2017

2017-07-14 13:42:17: antoine commented


Similar clibpoard crash backtrace: #1579.

@totaam
Copy link
Collaborator Author

totaam commented Jul 20, 2017

2017-07-20 10:32:58: antoine changed status from closed to reopened

@totaam
Copy link
Collaborator Author

totaam commented Jul 20, 2017

2017-07-20 10:32:58: antoine commented


This should be fixed on osx by #1588

@totaam
Copy link
Collaborator Author

totaam commented Aug 8, 2017

2017-08-08 01:13:05: afarr commented


Interesting to note. Tested some with 2.2 16657 osx client against the 2.2. 16657 fedora 25 server - does indeed seem fixed.

At one point, because of the old title of this ticket, I misunderstood and tried to set, client-side, the clipboard to just client-to-server, but got the syntax wrong... which, interestingly, caused the clipboard behavior to become incredibly erratic (--clipboard=to-server produced the warning: Warning: no clipboard types matching 'to-server', but as I tried to copy/paste it felt like I was getting almost random selections from the page when I tried to paste).

Let me know if you want a ticket to handle misbehavior triggered by invalid configure flags (as if you don't have enough to deal with making everything behave when it's properly configured).
In the meantime, I think I'm going to re-close this.

@totaam totaam closed this as completed Aug 8, 2017
@totaam
Copy link
Collaborator Author

totaam commented Aug 8, 2017

2017-08-08 07:35:50: antoine commented


When using invalid values with the --clipboard= switch, clipboard synchronization will be disabled, r16659 makes that clearer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant