fix automatic clipboard not working #7260
Signed-off-by: si458 <simonsmith5521@gmail.com>
si458 committed
Mar 24, 2026 at 10:26 UTC
5f8b74fa89fb9be8625de72f9b1d2a64f97a60a0
3 files changed
+80
-30
agents/meshcore.js
+2
-2
@@ -1590,14 +1590,14 @@ function handleServerCommand(data) {
1590
if (require('MeshAgent').isService) {
1591
require('clipboard').dispatchRead().then(function (str) {
1592
if (str) {
1593
- MeshServerLogEx(21, [str.length], "Getting clipboard content, " + str.length + " byte(s)", data);
1593
+ if (data.tag != 3) { MeshServerLogEx(21, [str.length], "Getting clipboard content, " + str.length + " byte(s)", data); }
1594
mesh.SendCommand({ action: 'msg', type: 'getclip', sessionid: data.sessionid, data: str, tag: data.tag });
1595
}
1596
});
1597
} else {
1598
require('clipboard').read().then(function (str) {
1599
if (str) {
1600
- MeshServerLogEx(21, [str.length], "Getting clipboard content, " + str.length + " byte(s)", data);
1600
+ if (data.tag != 3) { MeshServerLogEx(21, [str.length], "Getting clipboard content, " + str.length + " byte(s)", data); }
1601
mesh.SendCommand({ action: 'msg', type: 'getclip', sessionid: data.sessionid, data: str, tag: data.tag });
1602
}
1603
});
views/default.handlebars
+39
-14
@@ -1616,6 +1616,7 @@
1616
var deskKeyboardShortcuts = [];
1617
var deskKeyboardStrings = [];
1618
var deskLastClipboardSent = null;
1619
+ var deskLastClipboardReceived = null;
1620
var requestedLastConnects = false;
1621
var devicePagingState = null;
1622
@@ -2781,8 +2782,13 @@
2782
} else if ((message.type === 'getclip') && (currentNode != null) && (currentNode._id == message.nodeid)) {
2783
if ((message.tag == 1) && (xxdialogTag === 'clipboard')) {
2784
Q('d2clipText').value = message.data; // Put remote clipboard data into dialog box
2784
- } else if (message.tag === 2) {
2785
- if (navigator.clipboard != null) { navigator.clipboard.writeText(message.data).then(function() { }).catch(function(err) { console.log(err); }) } // Put remote clipboard data into our clipboard
2785
+ } else if ((message.tag === 2) || (message.tag === 3)) {
2786
+ // tag 2 = manual clipboard-in button, tag 3 = auto-clipboard poll
2787
+ if ((navigator.clipboard != null) && (message.data != deskLastClipboardReceived) && document.hasFocus()) {
2788
+ deskLastClipboardReceived = message.data;
2789
+ deskLastClipboardSent = message.data; // prevent echo back to remote
2790
+ navigator.clipboard.writeText(message.data).then(function() { }).catch(function(err) { });
2791
+ }
2792
}
2793
} else if ((message.type === 'setclip') && (xxdialogTag === 'clipboard') && (currentNode != null) && (currentNode._id == message.nodeid)) {
2794
// Display success/fail on the clipboard dialog box.
@@ -9769,7 +9775,15 @@
9775
case 3:
9776
if (desktop && (desktop.serverIsRecording == true)) { QV('deskRecordIcon', true); }
9777
desktop.startTime = new Date();
9772
- deskLastClipboardSent = null;
9778
+ deskLastClipboardReceived = null;
9779
+ // Pre-seed sent value with current local clipboard so we don't blast it to the remote on connect
9780
+ if ((navigator.clipboard != null) && (navigator.clipboard.readText != null) && (Mstsc.browser() != 'firefox')) {
9781
+ try {
9782
+ navigator.clipboard.readText().then(function(text) { deskLastClipboardSent = text; }).catch(function(err) { deskLastClipboardSent = null; });
9783
+ } catch (ex) { deskLastClipboardSent = null; }
9784
+ } else {
9785
+ deskLastClipboardSent = null;
9786
+ }
9787
if (updateSessionTimer == null) { updateSessionTimer = setInterval(updateSessionTime, 1000); }
9788
break;
9789
default:
@@ -9791,17 +9805,28 @@
9805
QH('DeskTimer', zeroPad(Math.floor(seconds / 3600), 2) + ':' + zeroPad((Math.floor(seconds / 60) % 60), 2) + ':' + zeroPad((seconds % 60), 2));
9806
QH('DeskLatency', latencyStr);
9807
// Auto-clipboard
9794
- if ((((desktop.contype != 4) && (desktopsettings.autoclipboard === true)) || ((desktop.contype == 4) && (desktopsettings.rdpautoclipboard === true))) && (navigator.clipboard != null) && (navigator.clipboard.readText != null)) {
9795
- if (Mstsc.browser() == 'firefox') return; // this is needed because firefox pops up a PASTE option every second which is annoying
9796
- try {
9797
- navigator.clipboard.readText().then(function(text) {
9798
- if (desktop == null) return;
9799
- if ((text != null) && (deskLastClipboardSent != text)) {
9800
- if (desktop.m.setClipboard) { desktop.m.setClipboard(text); } else { console.log('s3'); meshserver.send({ action: 'msg', type: 'setclip', nodeid: currentNode._id, data: text }); }
9801
- deskLastClipboardSent = text;
9802
- }
9803
- }).catch(function(err) { });
9804
- } catch (ex) { console.log(ex); }
9808
+ var autoClipEnabled = ((desktop.contype != 4) && (desktopsettings.autoclipboard === true)) || ((desktop.contype == 4) && (desktopsettings.rdpautoclipboard === true));
9809
+ if (autoClipEnabled && (navigator.clipboard != null)) {
9810
+ // Local -> Remote: skip on Firefox as readText triggers an annoying paste popup every second
9811
+ if ((Mstsc.browser() != 'firefox') && (navigator.clipboard.readText != null)) {
9812
+ try {
9813
+ navigator.clipboard.readText().then(function(text) {
9814
+ if (desktop == null) return;
9815
+ if ((text != null) && (deskLastClipboardSent != text)) {
9816
+ if (desktop.m.setClipboard) {
9817
+ desktop.m.setClipboard(text);
9818
+ } else {
9819
+ meshserver.send({ action: 'msg', type: 'setclip', nodeid: currentNode._id, data: text });
9820
+ }
9821
+ deskLastClipboardSent = text;
9822
+ }
9823
+ }).catch(function(err) { });
9824
+ } catch (ex) { console.log(ex); }
9825
+ }
9826
+ // Remote -> Local: poll remote clipboard every second (non-RDP only; RDP uses onClipboardChanged callback)
9827
+ if ((desktop.contype != 4) && (currentNode != null) && (navigator.clipboard.writeText != null)) {
9828
+ meshserver.send({ action: 'msg', type: 'getclip', nodeid: currentNode._id, tag: 3 });
9829
+ }
9830
}
9831
} else {
9832
QH('DeskTimer', '');
views/default3.handlebars
+39
-14
@@ -2132,6 +2132,7 @@
2132
var deskKeyboardShortcuts = [];
2133
var deskKeyboardStrings = [];
2134
var deskLastClipboardSent = null;
2135
+ var deskLastClipboardReceived = null;
2136
var requestedLastConnects = false;
2137
var devicePagingState = null;
2138
@@ -3453,8 +3454,13 @@
3454
} else if ((message.type === 'getclip') && (currentNode != null) && (currentNode._id == message.nodeid)) {
3455
if ((message.tag == 1) && (xxdialogTag === 'clipboard')) {
3456
Q('d2clipText').value = message.data; // Put remote clipboard data into dialog box
3456
- } else if (message.tag === 2) {
3457
- if (navigator.clipboard != null) { navigator.clipboard.writeText(message.data).then(function () { }).catch(function (err) { console.log(err); }) } // Put remote clipboard data into our clipboard
3457
+ } else if ((message.tag === 2) || (message.tag === 3)) {
3458
+ // tag 2 = manual clipboard-in button, tag 3 = auto-clipboard poll
3459
+ if ((navigator.clipboard != null) && (message.data != deskLastClipboardReceived) && document.hasFocus()) {
3460
+ deskLastClipboardReceived = message.data;
3461
+ deskLastClipboardSent = message.data; // prevent echo back to remote
3462
+ navigator.clipboard.writeText(message.data).then(function () { }).catch(function (err) { });
3463
+ }
3464
}
3465
} else if ((message.type === 'setclip') && (xxdialogTag === 'clipboard') && (currentNode != null) && (currentNode._id == message.nodeid)) {
3466
// Display success/fail on the clipboard dialog box.
@@ -10747,7 +10753,15 @@
10753
case 3:
10754
if (desktop && (desktop.serverIsRecording == true)) { QV('deskRecordIcon', true); }
10755
desktop.startTime = new Date();
10750
- deskLastClipboardSent = null;
10756
+ deskLastClipboardReceived = null;
10757
+ // Pre-seed sent value with current local clipboard so we don't blast it to the remote on connect
10758
+ if ((navigator.clipboard != null) && (navigator.clipboard.readText != null) && (Mstsc.browser() != 'firefox')) {
10759
+ try {
10760
+ navigator.clipboard.readText().then(function (text) { deskLastClipboardSent = text; }).catch(function (err) { deskLastClipboardSent = null; });
10761
+ } catch (ex) { deskLastClipboardSent = null; }
10762
+ } else {
10763
+ deskLastClipboardSent = null;
10764
+ }
10765
if (updateSessionTimer == null) { updateSessionTimer = setInterval(updateSessionTime, 1000); }
10766
break;
10767
default:
@@ -10769,17 +10783,28 @@
10783
QH('DeskTimer', zeroPad(Math.floor(seconds / 3600), 2) + ':' + zeroPad((Math.floor(seconds / 60) % 60), 2) + ':' + zeroPad((seconds % 60), 2));
10784
QH('DeskLatency', latencyStr);
10785
// Auto-clipboard
10772
- if ((((desktop.contype != 4) && (desktopsettings.autoclipboard === true)) || ((desktop.contype == 4) && (desktopsettings.rdpautoclipboard === true))) && (navigator.clipboard != null) && (navigator.clipboard.readText != null)) {
10773
- if (Mstsc.browser() == 'firefox') return; // this is needed because firefox pops up a PASTE option every second which is annoying
10774
- try {
10775
- navigator.clipboard.readText().then(function (text) {
10776
- if (desktop == null) return;
10777
- if ((text != null) && (deskLastClipboardSent != text)) {
10778
- if (desktop.m.setClipboard) { desktop.m.setClipboard(text); } else { console.log('s3'); meshserver.send({ action: 'msg', type: 'setclip', nodeid: currentNode._id, data: text }); }
10779
- deskLastClipboardSent = text;
10780
- }
10781
- }).catch(function (err) { });
10782
- } catch (ex) { console.log(ex); }
10786
+ var autoClipEnabled = ((desktop.contype != 4) && (desktopsettings.autoclipboard === true)) || ((desktop.contype == 4) && (desktopsettings.rdpautoclipboard === true));
10787
+ if (autoClipEnabled && (navigator.clipboard != null)) {
10788
+ // Local -> Remote: skip on Firefox as readText triggers an annoying paste popup every second
10789
+ if ((Mstsc.browser() != 'firefox') && (navigator.clipboard.readText != null)) {
10790
+ try {
10791
+ navigator.clipboard.readText().then(function (text) {
10792
+ if (desktop == null) return;
10793
+ if ((text != null) && (deskLastClipboardSent != text)) {
10794
+ if (desktop.m.setClipboard) {
10795
+ desktop.m.setClipboard(text);
10796
+ } else {
10797
+ meshserver.send({ action: 'msg', type: 'setclip', nodeid: currentNode._id, data: text });
10798
+ }
10799
+ deskLastClipboardSent = text;
10800
+ }
10801
+ }).catch(function (err) { });
10802
+ } catch (ex) { console.log(ex); }
10803
+ }
10804
+ // Remote -> Local: poll remote clipboard every second (non-RDP only; RDP uses onClipboardChanged callback)
10805
+ if ((desktop.contype != 4) && (currentNode != null) && (navigator.clipboard.writeText != null)) {
10806
+ meshserver.send({ action: 'msg', type: 'getclip', nodeid: currentNode._id, tag: 3 });
10807
+ }
10808
}
10809
} else {
10810
QH('DeskTimer', '');