OSC / ondemand

Supercomputing. Seamlessly. Open, Interactive HPC Via the Web
https://openondemand.org/
MIT License
293 stars 107 forks source link

noVNC clipboard resync on newline representation mismatch causing issues with GTK applications #3839

Open mw-a opened 1 month ago

mw-a commented 1 month ago

I had users complaining about being unable to copy'n'paste multiple files in XFCE's Thunar file manager in OOD Linux interactive desktop sessions.

GTK applications seem to remember names of files to copy separated by newlines and won't accept them back on paste separated by carriage return and newline.

The issue seems to be due to automatic noVNC clipboard sync changing newline (\n) to carriage return+newline (\r\n) (at least on Windows clients). On the next click on the noVNC canvas that is synced back verbatim to the remote server. The check at https://github.com/OSC/ondemand/blob/a5d0a0e98a0ef9d558955802eafb7aeeaf4e1bfc/apps/dashboard/public/noVNC-1.3.0/app/ui.js#L958 doesn't catch it because technically it differs in the additional carrage returns inserted by the client.

Conversely copy'n'pasting multiple files in Thunar works when not placing any additional mouse clicks between copying and inserting, be it Ctrl+c and Ctrl+v or using the context menu. If there are any other clicks inbetween, Thunar's Paste option will be deactivated in the context menu.

This is with Microsoft Edge 129.0.2792.65 and Google Chrome 129.0.6668.71 on Windows 10 and OOD 3.1.4. Firefox is not affected as it does not automatically sync the clipboard.

My workaround for now consist of this bit of code which basically prevents the return sync if contents only differ in newline representation which solves the issue for me:

--- ui.js.orig  2024-10-01 11:40:23.448666003 +0000
+++ ui.js       2024-10-01 12:07:58.413650826 +0000
@@ -955,7 +955,8 @@
             .then(() => navigator.clipboard.readText())
             .then((clipboardText) => {
                 const text = document.getElementById('noVNC_clipboard_text').value;
-                if (clipboardText !== text) {
+                const nlClipboardText = clipboardText.replace(/\r\n/g, "\n");
+                if (clipboardText !== text && nlClipboardText !== text) {
                     document.getElementById('noVNC_clipboard_text').value = clipboardText;
                     UI.clipboardSend();
                 }

Would this be considered a valid solution to the problem? If so, I can certainly turn it into a PR.

What might a better solution look like?

johrstrom commented 1 month ago

Hi, thanks for the issue and the possible resolution. I'll have to take a look at it in more depth, but on the surface what you have makes sense.