xpra icon
Bug tracker and wiki

Opened 5 years ago

Closed 4 months ago

Last modified 2 months ago

#812 closed task (fixed)

re-implement clipboard without nested main

Reported by: (none) Owned by: Antoine Martin
Priority: critical Milestone: 3.0
Component: core Version: trunk
Keywords: Cc: onlyjob@…

Description (last modified by Antoine Martin)

As it is, it is just too problematic: too many bugs to list, including some unresolved ones: #669, #452 (it is also causing hangs with #598). See also #2172, #2138

We should be able to rip it out and just use plain X11 calls (see ICCCM section 2: Peer-to-Peer Communication by Means of Selections), hopefully GTK won't get too confused by this...

We can keep the existing code, at least client side, for the non-X11 platforms.

Link: x-cut-and-paste

Attachments (1)

clipboard-win32.patch (8.7 KB) - added by totaamwin32 6 months ago.
win32 native clipboard work in progress

Download all attachments as: .zip

Change History (40)

comment:1 Changed 5 years ago by Antoine Martin

Status: newassigned

Another reason for doing this, just hit this today (not sure how):

RuntimeError: maximum recursion depth exceeded
Traceback (most recent call last):
  File "/usr/lib64/python2.7/site-packages/xpra/clipboard/clipboard_base.py", line 167, in _get_clipboard_from_remote_handler
Error in sys.excepthook:
Traceback (most recent call last):
  File "/usr/lib64/python2.7/site-packages/xpra/gtk_common/quit.py", line 67, in gtk_main_quit_on_fatal_exception
    print(traceback.print_exception(etype, val, tb))
  File "/usr/lib64/python2.7/traceback.py", line 125, in print_exception
    print_tb(tb, limit, file)
  File "/usr/lib64/python2.7/traceback.py", line 69, in print_tb
    line = linecache.getline(filename, lineno, f.f_globals)
  File "/usr/lib64/python2.7/linecache.py", line 14, in getline
    lines = getlines(filename, module_globals)
  File "/usr/lib64/python2.7/linecache.py", line 40, in getlines
    return updatecache(filename, module_globals)
RuntimeError: maximum recursion depth exceeded

Original exception was:
Traceback (most recent call last):
  File "/usr/lib64/python2.7/site-packages/xpra/clipboard/clipboard_base.py", line 167, in _get_clipboard_from_remote_handler
    log("get clipboard from remote handler id=%s", request_id)
RuntimeError: maximum recursion depth exceeded

comment:2 Changed 4 years ago by Antoine Martin

Description: modified (diff)

comment:3 Changed 4 years ago by onlyjob

Cc: onlyjob@… added

comment:4 Changed 4 years ago by Antoine Martin

comment:5 Changed 4 years ago by Antoine Martin

Milestone: 0.161.0

Re-scheduling due to lack of time.

Another item worth considering during the re-write would be to make all clipboards "greedy" like the win32 and osx ones, or at least having the option of doing that.

#1018 is a duplicate of this ticket.

Last edited 4 years ago by Antoine Martin (previous) (diff)

comment:8 Changed 3 years ago by Antoine Martin

Milestone: 1.03.0

Likely to be quite hard.

comment:9 Changed 2 years ago by Antoine Martin

See also: #1589 GTK3 clipboard support

comment:10 Changed 12 months ago by Antoine Martin

This should help fix bugs like #2025 and #2172

Last edited 8 months ago by Antoine Martin (previous) (diff)

comment:11 Changed 7 months ago by Antoine Martin

Priority: majorcritical

More problems (and yet more reported on IRC): #2138, see also #1844.

comment:12 Changed 7 months ago by Antoine Martin

Description: modified (diff)

comment:13 Changed 7 months ago by Antoine Martin

Summary: re-implement clipboard without gtk or nested mainre-implement clipboard without nested main

Preparatory steps added in r22212.

We can't completely do without GTK because the hooks for X11 events are in the gtk main loop filter, and the events are dispatched as gobject signals.
But at least it should be easier to move away from GTK at some point.

And we also need to use the xfixes API, because it's better.
See also #1494

Last edited 7 months ago by Antoine Martin (previous) (diff)

comment:14 Changed 7 months ago by Antoine Martin

Added:

The toy clipboard class can now send a receive clipboard data.

comment:15 Changed 7 months ago by Antoine Martin

Description: modified (diff)

Partial merge:

  • r22217 add time to property events
  • r22227 move nesting check so we can skip it
  • r22228 cosmetic
  • r22229 undo some of the really ugly original code from 2009! just use native struct formats directly rather than transforming them in the bindings
  • r22230 split clipboard base class so we can re-use the higher level logic without the low-level gtk bits

TODO:

  • rename private fields so the helper can access them without triggering warnings, ie: _can_send
  • handle COMPOUND_TEXT?
  • move code to proxy: local_to_remote?
  • XGetWindowProperty needs to handle large data (continue) - HARD!
  • do_owner_changed() should fire a new token every time? for greedy clients only?
  • emit_token needs to get TARGETS and the data before sending
  • we use the TARGET as part of the property name and maybe we shouldn't: in some cases the property name ends up looking like this: PRIMARY-text/plain;charset=utf-8 - is this always going to be a valid property name? could this be abused?
  • the same request can timeout in two places: the remote request timeout, remotely when the remote client takes too long. Both can trigger warning and delete the request_id..
Last edited 7 months ago by Antoine Martin (previous) (diff)

comment:16 Changed 7 months ago by Antoine Martin

Updates:

It works surprisingly well and does not ever lock the main thread!

Still TODO:

  • macos and win32 clipboard code so we can drop the GTK clipboard completely (new ticket? this may help: Writing a cross-platform clipboard library)
  • COMPOUND_TEXT and other targets: let clients specify blacklist?
  • XGetWindowProperty: maybe pass the maximum buffer size (and remove icon hack)
  • token needs data for greedy clients
  • handle timeouts
  • handle win32 token state mismatch issue

etc

Last edited 7 months ago by Antoine Martin (previous) (diff)

comment:17 Changed 6 months ago by Antoine Martin

Updates:

  • r22364 python3 fix
  • r22368 XGetWindowProperty fixed (4MB limit for clipboard transfers)
  • r22375: many improvements (see commit message)

Still TODO:

  • greedy clients and early sending of targets and target data
  • win32 and macos

comment:18 Changed 6 months ago by totaamwin32

win32 updates:

  • r22378 refactoring
  • r22380 add more clipboard ctypes function definitions

Changed 6 months ago by totaamwin32

Attachment: clipboard-win32.patch added

win32 native clipboard work in progress

comment:19 Changed 6 months ago by totaamwin32

updates:

  • r22401 handles "greedy" clients (ie: win32 and macos)
  • r22404 win32 clipboard implementation (disabled for now)
Last edited 6 months ago by Antoine Martin (previous) (diff)

comment:20 Changed 6 months ago by Antoine Martin

Updates:

  • r22466 debug logging
  • r22467 null terminate strings on win32
  • r22468 use new win32 backend by default
  • r22427 better error logging for atom errors

comment:21 Changed 6 months ago by Antoine Martin

Updates:

  • r22470 add blacklist for clipit, just send empty reply
  • r22475 don't bother sending events for selections that are not enabled
  • r22476 + r22477: refactoring of translated clipboards (osx and win32)
  • r22478: osx fix
  • r22481 improve win32 clipboard: handle greedy clients, block-owner-change

We do have to deal with the macos clipboard to be able to cleanup the codebase and remove the legacy gdk clipboard classes.

Last edited 6 months ago by Antoine Martin (previous) (diff)

comment:22 Changed 6 months ago by Antoine Martin

Caused a regression: #2280.

comment:23 Changed 6 months ago by Antoine Martin

#2280 fixed in r22501, we don't release the selection on exit to avoid this GTK3 crash.
Ideally, we should find a way to release the selection without crashing GTK3 but this will do for now.

comment:24 Changed 6 months ago by Antoine Martin

Updates:

Still TODO:

  • win32 client still receiving PRIMARY tokens when it should not
  • verify backwards compatibility
  • update #273
Last edited 6 months ago by Antoine Martin (previous) (diff)

comment:25 Changed 6 months ago by Antoine Martin

Owner: changed from Antoine Martin to Jonathan Anthony
Reporter: Antoine Martin deleted
Status: assignednew

Updates:

  • translated clipboard fixes in r22569
  • fix token warnings in r22570
  • backwards compatibility verified with 2.5.x clients

This will do for this ticket, will follow up in #273.

@encodedEntropy: this really needs testing, ideally before #1844 so if anything is broken then we will know if it's here or there.

comment:26 Changed 5 months ago by Antoine Martin

Owner: changed from Jonathan Anthony to Antoine Martin
Status: newassigned

Something's not right.
When copying an image from eog on the server (testing for #1494):

do_owner_changed()
_send_clipboard_token_handler(X11ClipboardProxy(CLIPBOARD), ())

requesting local XConvertSelection from 'Image Viewer' for 'TARGETS' into 'CLIPBOARD-TARGETS'
client @25.162 got token, selection=CLIPBOARD, targets=None, target data=None, claim=True, can-receive=True
_send_clipboard_token_handler(X11ClipboardProxy(CLIPBOARD), (('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'image/png', 'image/bmp', 'image/x-bmp', 'image/x-MS-bmp', 'image/x-icon', 'image/x-ico', 'image/x

Why do we request the targets and send a clipboard-token to the client without them? Do one or the other!

Then immediately, gedit and Terminal are being greedy and requesting the targets:

client @25.164 clipboard request for CLIPBOARD from window 0x3400125: 'gedit'
client @25.166 clipboard request for CLIPBOARD from window 0x2400002: 'Terminal'

We get the targets again:

proxy_got_contents(6, CLIPBOARD, TARGETS, ATOM, 32, <class 'bytes'>:192) data=0xa001...

And send them to the client:

client @25.167 got token, selection=CLIPBOARD, targets=(b'TIMESTAMP', b'TARGETS', b'MULTIPLE', b'image/png', b'image/bmp', b'image/x-bmp', b'image/x-MS-bmp', b'image/x-icon', b'image/x-ico', b'image/x-win-bitmap', b'image/vnd.microsoft.icon', b'application/ico', b'image/ico', b'image/icon', b'text/ico', b'image/jpeg', b'image/tiff', b'UTF8_STRING', b'COMPOUND_TEXT', b'TEXT', b'STRING', b'text/plain;charset=utf-8', b'text/plain', b'text/uri-list'), target data=None, claim=True, can-receive=True

We should filter the image/FORMAT list to only contain formats that we can process through pillow.

We tell both gedit and Terminal about the targets:

client @25.168 setting response b'\x99\x01\x00\x00.. ..\x00\x00' to property GDK_SELECTION of window 'gedit' as ATOM
client @25.168 setting response b'\x99\x01\x00\x00.. ..\x00\x00' to property GDK_SELECTION of window 'Terminal' as ATOM

Probably because we claim the clipboard again when handling this token, they request the targets again, and we respond with the cached value:

client @25.171 clipboard request for CLIPBOARD from window 0x3400125: 'gedit'
client @25.171 using existing TARGETS value as response
client @25.172 clipboard request for CLIPBOARD from window 0x2400002: 'Terminal'
client @25.172 using existing TARGETS value as response

When trying to paste it into the gimp, it requests the data in image/png format:

client @19.259 clipboard request for CLIPBOARD from window 0x42029cd: 'GNU Image Manipulation Program'
client @19.259 using existing TARGETS value as response
client @19.264 clipboard request for CLIPBOARD from window 0x42029cd: 'GNU Image Manipulation Program'
client @19.264 send_clipboard_request_handler(X11ClipboardProxy(CLIPBOARD), 'CLIPBOARD', 'image/png')

The server tries to honour it:

requesting local XConvertSelection from 'Image Viewer' for 'image/png' into 'CLIPBOARD-image/png'
proxy_got_contents(1, CLIPBOARD, image/png, INCR, 32, <class 'bytes'>:8) data=0x470b040000000000..

This fails:

xpra.x11.bindings.window_bindings.BadPropertyType: incomplete data: 196608 bytes after

Because we don't handle INCR and don't handle multipart?

Version 0, edited 5 months ago by Antoine Martin (next)

comment:27 Changed 5 months ago by Antoine Martin

r22824 adds support for incremental transfers IN. (+minor fixup in r22825)

Still TODO:

  • incremental transfers OUT? (meh - works without)
  • from comment:26, "why do we request the targets and send a clipboard-token to the client without them? Do one or the other!"
  • we should not cache the target data for so long - I've seen it get wedged with outdated buffers
  • targets filters: allow whitelisted mimetypes?
  • poc image filter
Last edited 5 months ago by Antoine Martin (previous) (diff)

comment:28 Changed 5 months ago by Antoine Martin

added PoC overlay code in r22826 from both images and timestamp, only for png images for now.

comment:29 Changed 5 months ago by Antoine Martin

Supporting this in the html5 client is going to be difficult, #1844 may help.
See:

  • chromium bug: Support programmatical copying of images to clipboard: The CL enables a feature that has been available under the "Enable experimental Web Platform features" flag since M75, so we think that the code is solid and there are no crashers lurking in there. (updated today!)
  • Unblocking Clipboard Access: There are more generic read() and write() methods in the specification, but these come with additional implementation complexity and security concerns (remember those image bombs?). For now, Chrome is rolling out the simpler text parts of the API. - we can deal with the image bombs by using the pillow image filter
  • Clipboard API and events : Async Clipboard API: An image that is specially crafted to exploit bugs in the core OS image handling code can be written to the clipboard (same)

comment:30 Changed 5 months ago by Antoine Martin

Moving html5 to #2312.

comment:31 Changed 4 months ago by Antoine Martin

The double requests issue from comment:26 is fixed in r22856.

comment:32 Changed 4 months ago by Antoine Martin

Unrestricted html5 clipboard access (at least for chrome): #2320.

comment:33 Changed 4 months ago by Antoine Martin

See also brotli compression for text: #2289

comment:34 Changed 4 months ago by Antoine Martin

Resolution: fixed
Status: assignedclosed

Works well enough for this release. Closing.

Issues should be filed as new bugs, pointing back to this ticket.

comment:35 Changed 4 months ago by Antoine Martin

Minor improvements:

See also updates in #1844.

comment:36 Changed 4 months ago by Antoine Martin

Another regression spotted: ticket:2338#comment:3.

comment:37 Changed 3 months ago by Antoine Martin

Updates:

comment:38 Changed 3 months ago by Antoine Martin

The unit tests found a bug: r23215.
They are now also enabled for python3: r23219.

comment:39 Changed 3 months ago by Antoine Martin

Clipboard won't work well at all with wayland clients, even if we re-added the GTK code (see ticket:2243#comment:10).

comment:40 Changed 3 months ago by Antoine Martin

Clipboard did not work with xsettings=no (#2342), that's because the new clipboard needs to listen for root window events. Fixed in r23369.

comment:41 Changed 2 months ago by Antoine Martin

The nested-main-loop code is finally removed in r23470.

Note: See TracTickets for help on using tickets.