Skip to content

Commit

Permalink
Merge pull request yuvipanda#10 from manics/clipboard
Browse files Browse the repository at this point in the history
Add a shared clipboard
  • Loading branch information
yuvipanda authored Jan 14, 2023
2 parents d9438d4 + 67a8425 commit 24a2568
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 10 deletions.
1 change: 1 addition & 0 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ channels:
- conda-forge
dependencies:
- jupyter-server-proxy>=1.4
- jupyterhub-singleuser
- pip
- websockify
- pip:
Expand Down
65 changes: 63 additions & 2 deletions jupyter_desktop/share/web/noVNC-1.2.0/vnc_lite.html
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,36 @@
overflow: hidden;
}

/* Clipboard */
#noVNC_clipboard_area {
position: fixed;
top: 0px;
left: 0px;
}
#noVNC_clipboard_button {
border: 1px outset;
cursor: pointer;
}
#noVNC_clipboard_button img {
height: 24px;
vertical-align: middle;
}
#noVNC_clipboard_button .label {
padding: 5px 5px 4px 0px;
}
#noVNC_clipboard {
/* Full screen, minus padding and left and right margins */
max-width: calc(100vw - 2*15px - 75px - 25px);
background-color: #6e84a3;
}
.noVNC_clipboard_closed #noVNC_clipboard {
display: none;
}
#noVNC_clipboard_text {
width: 500px;
max-width: 100%;
}

</style>

<!-- Promise polyfill for IE11 -->
Expand Down Expand Up @@ -146,7 +176,7 @@
const host = readQueryVariable('host', window.location.hostname);
let port = readQueryVariable('port', window.location.port);
const password = readQueryVariable('password');
// MODIFICATION FROM vnc_lite.html

const path = readQueryVariable('path', window.location.pathname.replace(/[^/]*$/, '').substring(1) + 'websockify');

// | | | | | |
Expand Down Expand Up @@ -180,14 +210,45 @@

// Set parameters that can be changed on an active connection
rfb.viewOnly = readQueryVariable('view_only', false);
// MODIFICATION FROM vnc_lite.html

rfb.scaleViewport = readQueryVariable('scale', true);

// Clipboard
function toggleClipboardPanel() {
document.getElementById('noVNC_clipboard_area').classList.toggle('noVNC_clipboard_closed');
}
document.getElementById("noVNC_clipboard_button")
.addEventListener('click', toggleClipboardPanel);

function clipboardReceive(e) {
document.getElementById('noVNC_clipboard_text').value = e.detail.text;
}
rfb.addEventListener("clipboard", clipboardReceive);

function clipboardSend() {
const text = document.getElementById('noVNC_clipboard_text').value;
rfb.clipboardPasteFrom(text);
}
document.getElementById("noVNC_clipboard_text")
.addEventListener('change', clipboardSend);

</script>
</head>

<body>
<div id="top_bar">
<div id="status">Loading</div>

<!-- Clipboard -->
<div id="noVNC_clipboard_area" class="noVNC_clipboard_closed">
<div id="noVNC_clipboard_button"><img src="app/images/clipboard.svg" />
<span class="label">Clipboard</span>
</div>
<div id="noVNC_clipboard">
<textarea id="noVNC_clipboard_text" rows=5></textarea>
</div>
</div>

<div id="sendCtrlAltDelButton">Send CtrlAltDel</div>
</div>
<div id="screen">
Expand Down
88 changes: 80 additions & 8 deletions jupyter_desktop/share/web/novnc-vnc_lite.html.patch
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
diff --git a/jupyter_desktop/share/web/noVNC-1.2.0/vnc_lite.html b/jupyter_desktop/share/web/noVNC-1.2.0/vnc_lite.html
index d17ab9e..a9e3e9b 100644
--- a/jupyter_desktop/share/web/noVNC-1.2.0/vnc_lite.html
+++ b/jupyter_desktop/share/web/noVNC-1.2.0/vnc_lite.html
--- jupyter_desktop/share/web/noVNC-1.2.0/vnc_lite.html.orig 2021-07-23 15:53:07.951581766 +0100
+++ jupyter_desktop/share/web/noVNC-1.2.0/vnc_lite.html 2021-07-23 15:52:29.893284532 +0100
@@ -3,6 +3,8 @@
<head>

Expand All @@ -11,23 +9,97 @@ index d17ab9e..a9e3e9b 100644
noVNC example: lightweight example using minimal UI and features

This is a self-contained file which doesn't import WebUtil or external CSS.
@@ -144,7 +146,8 @@
@@ -59,6 +61,36 @@
overflow: hidden;
}

+ /* Clipboard */
+ #noVNC_clipboard_area {
+ position: fixed;
+ top: 0px;
+ left: 0px;
+ }
+ #noVNC_clipboard_button {
+ border: 1px outset;
+ cursor: pointer;
+ }
+ #noVNC_clipboard_button img {
+ height: 24px;
+ vertical-align: middle;
+ }
+ #noVNC_clipboard_button .label {
+ padding: 5px 5px 4px 0px;
+ }
+ #noVNC_clipboard {
+ /* Full screen, minus padding and left and right margins */
+ max-width: calc(100vw - 2*15px - 75px - 25px);
+ background-color: #6e84a3;
+ }
+ .noVNC_clipboard_closed #noVNC_clipboard {
+ display: none;
+ }
+ #noVNC_clipboard_text {
+ width: 500px;
+ max-width: 100%;
+ }
+
</style>

<!-- Promise polyfill for IE11 -->
@@ -144,7 +176,8 @@
const host = readQueryVariable('host', window.location.hostname);
let port = readQueryVariable('port', window.location.port);
const password = readQueryVariable('password');
- const path = readQueryVariable('path', 'websockify');
+ // MODIFICATION FROM vnc_lite.html
+
+ const path = readQueryVariable('path', window.location.pathname.replace(/[^/]*$/, '').substring(1) + 'websockify');

// | | | | | |
// | | | Connect | | |
@@ -177,7 +180,8 @@
@@ -177,13 +210,45 @@

// Set parameters that can be changed on an active connection
rfb.viewOnly = readQueryVariable('view_only', false);
- rfb.scaleViewport = readQueryVariable('scale', false);
+ // MODIFICATION FROM vnc_lite.html
+
+ rfb.scaleViewport = readQueryVariable('scale', true);
+
+ // Clipboard
+ function toggleClipboardPanel() {
+ document.getElementById('noVNC_clipboard_area').classList.toggle('noVNC_clipboard_closed');
+ }
+ document.getElementById("noVNC_clipboard_button")
+ .addEventListener('click', toggleClipboardPanel);
+
+ function clipboardReceive(e) {
+ document.getElementById('noVNC_clipboard_text').value = e.detail.text;
+ }
+ rfb.addEventListener("clipboard", clipboardReceive);
+
+ function clipboardSend() {
+ const text = document.getElementById('noVNC_clipboard_text').value;
+ rfb.clipboardPasteFrom(text);
+ }
+ document.getElementById("noVNC_clipboard_text")
+ .addEventListener('change', clipboardSend);
+
</script>
</head>

<body>
<div id="top_bar">
<div id="status">Loading</div>
+
+ <!-- Clipboard -->
+ <div id="noVNC_clipboard_area" class="noVNC_clipboard_closed">
+ <div id="noVNC_clipboard_button"><img src="app/images/clipboard.svg" />
+ <span class="label">Clipboard</span>
+ </div>
+ <div id="noVNC_clipboard">
+ <textarea id="noVNC_clipboard_text" rows=5></textarea>
+ </div>
+ </div>
+
<div id="sendCtrlAltDelButton">Send CtrlAltDel</div>
</div>
<div id="screen">

0 comments on commit 24a2568

Please sign in to comment.