This commit is contained in:
Daniel Hammerschmidt 2025-11-10 18:02:21 -06:00 committed by GitHub
commit 6b9688ef21
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 78 additions and 9 deletions

View File

@ -185,6 +185,8 @@ const UI = {
UI.initSetting('bell', 'on'); UI.initSetting('bell', 'on');
UI.initSetting('view_only', false); UI.initSetting('view_only', false);
UI.initSetting('show_dot', false); UI.initSetting('show_dot', false);
UI.initSetting('show_local_cursor', false);
UI.initSetting('show_drag_cursor', false);
UI.initSetting('path', 'websockify'); UI.initSetting('path', 'websockify');
UI.initSetting('repeaterID', ''); UI.initSetting('repeaterID', '');
UI.initSetting('reconnect', false); UI.initSetting('reconnect', false);
@ -371,6 +373,10 @@ const UI = {
UI.addSettingChangeHandler('view_only', UI.updateViewOnly); UI.addSettingChangeHandler('view_only', UI.updateViewOnly);
UI.addSettingChangeHandler('show_dot'); UI.addSettingChangeHandler('show_dot');
UI.addSettingChangeHandler('show_dot', UI.updateShowDotCursor); UI.addSettingChangeHandler('show_dot', UI.updateShowDotCursor);
UI.addSettingChangeHandler('show_local_cursor');
UI.addSettingChangeHandler('show_local_cursor', UI.updateShowLocalCursor);
UI.addSettingChangeHandler('show_drag_cursor');
UI.addSettingChangeHandler('show_drag_cursor', UI.updateShowDragCursor);
UI.addSettingChangeHandler('host'); UI.addSettingChangeHandler('host');
UI.addSettingChangeHandler('port'); UI.addSettingChangeHandler('port');
UI.addSettingChangeHandler('path'); UI.addSettingChangeHandler('path');
@ -1101,6 +1107,8 @@ const UI = {
UI.rfb.qualityLevel = parseInt(UI.getSetting('quality')); UI.rfb.qualityLevel = parseInt(UI.getSetting('quality'));
UI.rfb.compressionLevel = parseInt(UI.getSetting('compression')); UI.rfb.compressionLevel = parseInt(UI.getSetting('compression'));
UI.rfb.showDotCursor = UI.getSetting('show_dot'); UI.rfb.showDotCursor = UI.getSetting('show_dot');
UI.rfb.showLocalCursor = UI.getSetting('show_local_cursor');
UI.rfb.showDragCursor = UI.getSetting('show_drag_cursor');
UI.updateViewOnly(); // requires UI.rfb UI.updateViewOnly(); // requires UI.rfb
UI.updateClipboard(); UI.updateClipboard();
@ -1809,6 +1817,16 @@ const UI = {
UI.rfb.showDotCursor = UI.getSetting('show_dot'); UI.rfb.showDotCursor = UI.getSetting('show_dot');
}, },
updateShowLocalCursor() {
if (!UI.rfb) return;
UI.rfb.showLocalCursor = UI.getSetting('show_local_cursor');
},
updateShowDragCursor() {
if (!UI.rfb) return;
UI.rfb.showDragCursor = UI.getSetting('show_drag_cursor');
},
updateLogging() { updateLogging() {
WebUtil.initLogging(UI.getSetting('logging')); WebUtil.initLogging(UI.getSetting('logging'));
}, },

View File

@ -295,16 +295,18 @@ export default class RFB extends EventTargetMixin {
// ===== PROPERTIES ===== // ===== PROPERTIES =====
this.dragViewport = false;
this.focusOnClick = true; this.focusOnClick = true;
this._viewOnly = false; this._viewOnly = false;
this._clipViewport = false; this._clipViewport = false;
this._clippingViewport = false; this._clippingViewport = false;
this._dragViewport = false;
this._scaleViewport = false; this._scaleViewport = false;
this._resizeSession = false; this._resizeSession = false;
this._showDotCursor = false; this._showDotCursor = false;
this._showLocalCursor = false;
this._showDragCursor = false;
this._qualityLevel = 6; this._qualityLevel = 6;
this._compressionLevel = 2; this._compressionLevel = 2;
@ -349,6 +351,12 @@ export default class RFB extends EventTargetMixin {
this._updateClip(); this._updateClip();
} }
get dragViewport() { return this._dragViewport; }
set dragViewport(dragViewport) {
this._dragViewport = dragViewport;
this._refreshCursor();
}
get scaleViewport() { return this._scaleViewport; } get scaleViewport() { return this._scaleViewport; }
set scaleViewport(scale) { set scaleViewport(scale) {
this._scaleViewport = scale; this._scaleViewport = scale;
@ -377,6 +385,18 @@ export default class RFB extends EventTargetMixin {
this._refreshCursor(); this._refreshCursor();
} }
get showLocalCursor() { return this._showLocalCursor; }
set showLocalCursor(show) {
this._showLocalCursor = show;
this._refreshCursor();
}
get showDragCursor() { return this._showDragCursor; }
set showDragCursor(show) {
this._showDragCursor = show;
this._refreshCursor();
}
get background() { return this._screen.style.background; } get background() { return this._screen.style.background; }
set background(cssValue) { this._screen.style.background = cssValue; } set background(cssValue) { this._screen.style.background = cssValue; }
@ -1118,11 +1138,16 @@ export default class RFB extends EventTargetMixin {
let bmask = RFB._convertButtonMask(ev.buttons); let bmask = RFB._convertButtonMask(ev.buttons);
let down = ev.type == 'mousedown'; let down = false;
switch (ev.type) { switch (ev.type) {
case 'mousedown': case 'mousedown':
down = true;
// eslint-disable-next-line no-fallthrough
case 'mouseup': case 'mouseup':
if (this.dragViewport) { if (this.dragViewport) {
if (this._showDragCursor) {
this._cursor.setLocalCursor(down ? 'grabbing' : 'grab');
}
if (down && !this._viewportDragging) { if (down && !this._viewportDragging) {
this._viewportDragging = true; this._viewportDragging = true;
this._viewportDragPos = {'x': pos.x, 'y': pos.y}; this._viewportDragPos = {'x': pos.x, 'y': pos.y};
@ -1341,7 +1366,7 @@ export default class RFB extends EventTargetMixin {
this._handleTapEvent(ev, 0x2); this._handleTapEvent(ev, 0x2);
break; break;
case 'drag': case 'drag':
if (this.dragViewport) { if (this._dragViewport) {
this._viewportHasMoved = false; this._viewportHasMoved = false;
this._viewportDragging = true; this._viewportDragging = true;
this._viewportDragPos = {'x': pos.x, 'y': pos.y}; this._viewportDragPos = {'x': pos.x, 'y': pos.y};
@ -1351,7 +1376,7 @@ export default class RFB extends EventTargetMixin {
} }
break; break;
case 'longpress': case 'longpress':
if (this.dragViewport) { if (this._dragViewport) {
// If dragViewport is true, we need to wait to see // If dragViewport is true, we need to wait to see
// if we have dragged outside the threshold before // if we have dragged outside the threshold before
// sending any events to the server. // sending any events to the server.
@ -1383,7 +1408,7 @@ export default class RFB extends EventTargetMixin {
break; break;
case 'drag': case 'drag':
case 'longpress': case 'longpress':
if (this.dragViewport) { if (this._dragViewport) {
this._viewportDragging = true; this._viewportDragging = true;
const deltaX = this._viewportDragPos.x - pos.x; const deltaX = this._viewportDragPos.x - pos.x;
const deltaY = this._viewportDragPos.y - pos.y; const deltaY = this._viewportDragPos.y - pos.y;
@ -1458,7 +1483,7 @@ export default class RFB extends EventTargetMixin {
case 'twodrag': case 'twodrag':
break; break;
case 'drag': case 'drag':
if (this.dragViewport) { if (this._dragViewport) {
this._viewportDragging = false; this._viewportDragging = false;
} else { } else {
this._fakeMouseMove(ev, pos.x, pos.y); this._fakeMouseMove(ev, pos.x, pos.y);
@ -1472,7 +1497,7 @@ export default class RFB extends EventTargetMixin {
break; break;
} }
if (this.dragViewport && !this._viewportHasMoved) { if (this._dragViewport && !this._viewportHasMoved) {
this._fakeMouseMove(ev, pos.x, pos.y); this._fakeMouseMove(ev, pos.x, pos.y);
// If dragViewport is true, we need to wait to see // If dragViewport is true, we need to wait to see
// if we have dragged outside the threshold before // if we have dragged outside the threshold before
@ -3047,7 +3072,7 @@ export default class RFB extends EventTargetMixin {
_shouldShowDotCursor() { _shouldShowDotCursor() {
// Called when this._cursorImage is updated // Called when this._cursorImage is updated
if (!this._showDotCursor) { if (!this._showDotCursor || (this._dragViewport && this._showDragCursor)) {
// User does not want to see the dot, so... // User does not want to see the dot, so...
return false; return false;
} }
@ -3077,6 +3102,13 @@ export default class RFB extends EventTargetMixin {
image.hotx, image.hoty, image.hotx, image.hoty,
image.w, image.h image.w, image.h
); );
if (this._dragViewport && this._showDragCursor) {
this._cursor.setLocalCursor(this._viewportDragging ? 'grabbing' : 'grab');
} else if (this._showLocalCursor) {
this._cursor.setLocalCursor('default');
} else {
this._cursor.setLocalCursor('none');
}
} }
static genDES(password, challenge) { static genDES(password, challenge) {

View File

@ -106,7 +106,7 @@ export default class Cursor {
} }
clear() { clear() {
this._target.style.cursor = 'none'; this.setLocalCursor('none');
this._canvas.width = 0; this._canvas.width = 0;
this._canvas.height = 0; this._canvas.height = 0;
this._position.x = this._position.x + this._hotSpot.x; this._position.x = this._position.x + this._hotSpot.x;
@ -115,6 +115,10 @@ export default class Cursor {
this._hotSpot.y = 0; this._hotSpot.y = 0;
} }
setLocalCursor(cursor) {
this._target.style.cursor = cursor;
}
// Mouse events might be emulated, this allows // Mouse events might be emulated, this allows
// moving the cursor in such cases // moving the cursor in such cases
move(clientX, clientY) { move(clientX, clientY) {

View File

@ -296,6 +296,20 @@
Show dot when no cursor Show dot when no cursor
</label> </label>
</li> </li>
<li>
<label>
<input id="noVNC_setting_show_local_cursor" type="checkbox"
class="toggle">
Show local cursor
</label>
</li>
<li>
<label>
<input id="noVNC_setting_show_drag_cursor" type="checkbox"
class="toggle">
Show drag cursor
</label>
</li>
<li><hr></li> <li><hr></li>
<!-- Logging selection dropdown --> <!-- Logging selection dropdown -->
<li> <li>

View File

@ -165,6 +165,7 @@
// Set parameters that can be changed on an active connection // Set parameters that can be changed on an active connection
rfb.viewOnly = readQueryVariable('view_only', false); rfb.viewOnly = readQueryVariable('view_only', false);
rfb.scaleViewport = readQueryVariable('scale', false); rfb.scaleViewport = readQueryVariable('scale', false);
rfb.showLocalCursor = readQueryVariable('show_local_cursor', 0);
</script> </script>
</head> </head>