Merge 702302fcc5 into 44b7489e73
This commit is contained in:
commit
5dd0c93c43
|
|
@ -178,6 +178,7 @@ const UI = {
|
||||||
UI.initSetting('password');
|
UI.initSetting('password');
|
||||||
UI.initSetting('autoconnect', false);
|
UI.initSetting('autoconnect', false);
|
||||||
UI.initSetting('view_clip', false);
|
UI.initSetting('view_clip', false);
|
||||||
|
UI.initSetting('view_drag', false);
|
||||||
UI.initSetting('resize', 'off');
|
UI.initSetting('resize', 'off');
|
||||||
UI.initSetting('quality', 6);
|
UI.initSetting('quality', 6);
|
||||||
UI.initSetting('compression', 2);
|
UI.initSetting('compression', 2);
|
||||||
|
|
@ -1096,11 +1097,17 @@ const UI = {
|
||||||
UI.rfb.addEventListener("bell", UI.bell);
|
UI.rfb.addEventListener("bell", UI.bell);
|
||||||
UI.rfb.addEventListener("desktopname", UI.updateDesktopName);
|
UI.rfb.addEventListener("desktopname", UI.updateDesktopName);
|
||||||
UI.rfb.clipViewport = UI.getSetting('view_clip');
|
UI.rfb.clipViewport = UI.getSetting('view_clip');
|
||||||
|
UI.rfb.dragViewport = UI.getSetting('view_drag');
|
||||||
UI.rfb.scaleViewport = UI.getSetting('resize') === 'scale';
|
UI.rfb.scaleViewport = UI.getSetting('resize') === 'scale';
|
||||||
UI.rfb.resizeSession = UI.getSetting('resize') === 'remote';
|
UI.rfb.resizeSession = UI.getSetting('resize') === 'remote';
|
||||||
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 = {
|
||||||
|
drag: 'grab',
|
||||||
|
dragging: 'grabbing',
|
||||||
|
empty: 'default',
|
||||||
|
};
|
||||||
|
|
||||||
UI.updateViewOnly(); // requires UI.rfb
|
UI.updateViewOnly(); // requires UI.rfb
|
||||||
},
|
},
|
||||||
|
|
|
||||||
115
core/rfb.js
115
core/rfb.js
|
|
@ -233,6 +233,14 @@ export default class RFB extends EventTargetMixin {
|
||||||
|
|
||||||
// Cursor
|
// Cursor
|
||||||
this._cursor = new Cursor();
|
this._cursor = new Cursor();
|
||||||
|
this._showLocalCursor = false;
|
||||||
|
this._localCursors = {
|
||||||
|
dragging: null,
|
||||||
|
drag: null,
|
||||||
|
viewOnly: null,
|
||||||
|
default: null,
|
||||||
|
empty: null,
|
||||||
|
};
|
||||||
|
|
||||||
// XXX: TightVNC 2.8.11 sends no cursor at all until Windows changes
|
// XXX: TightVNC 2.8.11 sends no cursor at all until Windows changes
|
||||||
// it. Result: no cursor at all until a window border or an edit field
|
// it. Result: no cursor at all until a window border or an edit field
|
||||||
|
|
@ -290,12 +298,12 @@ 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;
|
||||||
|
|
||||||
|
|
@ -315,8 +323,10 @@ export default class RFB extends EventTargetMixin {
|
||||||
this._rfbConnectionState === "connected") {
|
this._rfbConnectionState === "connected") {
|
||||||
if (viewOnly) {
|
if (viewOnly) {
|
||||||
this._keyboard.ungrab();
|
this._keyboard.ungrab();
|
||||||
|
this._refreshCursor();
|
||||||
} else {
|
} else {
|
||||||
this._keyboard.grab();
|
this._keyboard.grab();
|
||||||
|
this._refreshCursor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -342,6 +352,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;
|
||||||
|
|
@ -370,6 +386,29 @@ export default class RFB extends EventTargetMixin {
|
||||||
this._refreshCursor();
|
this._refreshCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get showLocalCursor() { return this._showLocalCursor; }
|
||||||
|
set showLocalCursor(cursors) {
|
||||||
|
cursors ??= false;
|
||||||
|
this._showLocalCursor = !!cursors;
|
||||||
|
const {
|
||||||
|
default: defaultCursor,
|
||||||
|
viewOnly: viewOnlyCursor,
|
||||||
|
drag: dragCursor,
|
||||||
|
dragging: draggingCursor,
|
||||||
|
empty: emptyCursor,
|
||||||
|
} = cursors;
|
||||||
|
defaultCursor && (this._localCursors.default = defaultCursor);
|
||||||
|
viewOnlyCursor && (this._localCursors.viewOnly = viewOnlyCursor);
|
||||||
|
dragCursor && (this._localCursors.drag = dragCursor);
|
||||||
|
draggingCursor && (this._localCursors.dragging = draggingCursor);
|
||||||
|
emptyCursor && (this._localCursors.empty = emptyCursor);
|
||||||
|
this._cursor.detach();
|
||||||
|
this._cursor.attach(this._canvas, {
|
||||||
|
showLocalCursor: this._showLocalCursor,
|
||||||
|
});
|
||||||
|
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; }
|
||||||
|
|
||||||
|
|
@ -574,7 +613,9 @@ export default class RFB extends EventTargetMixin {
|
||||||
|
|
||||||
this._gestures.attach(this._canvas);
|
this._gestures.attach(this._canvas);
|
||||||
|
|
||||||
this._cursor.attach(this._canvas);
|
this._cursor.attach(this._canvas, {
|
||||||
|
showLocalCursor: this._showLocalCursor
|
||||||
|
});
|
||||||
this._refreshCursor();
|
this._refreshCursor();
|
||||||
|
|
||||||
// Monitor size changes of the screen element
|
// Monitor size changes of the screen element
|
||||||
|
|
@ -1111,16 +1152,23 @@ 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 (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};
|
||||||
this._viewportHasMoved = false;
|
this._viewportHasMoved = false;
|
||||||
|
|
||||||
|
if (this._showLocalCursor) {
|
||||||
|
this._refreshCursor();
|
||||||
|
this._cursor.detach();
|
||||||
|
}
|
||||||
|
|
||||||
this._flushMouseMoveTimer(pos.x, pos.y);
|
this._flushMouseMoveTimer(pos.x, pos.y);
|
||||||
|
|
||||||
// Skip sending mouse events, instead save the current
|
// Skip sending mouse events, instead save the current
|
||||||
|
|
@ -1130,6 +1178,13 @@ export default class RFB extends EventTargetMixin {
|
||||||
} else {
|
} else {
|
||||||
this._viewportDragging = false;
|
this._viewportDragging = false;
|
||||||
|
|
||||||
|
if (this._showLocalCursor) {
|
||||||
|
this._cursor.attach(this._canvas, {
|
||||||
|
showLocalCursor: this._showLocalCursor,
|
||||||
|
});
|
||||||
|
this._refreshCursor();
|
||||||
|
}
|
||||||
|
|
||||||
// If we actually performed a drag then we are done
|
// If we actually performed a drag then we are done
|
||||||
// here and should not send any mouse events
|
// here and should not send any mouse events
|
||||||
if (this._viewportHasMoved) {
|
if (this._viewportHasMoved) {
|
||||||
|
|
@ -1334,7 +1389,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};
|
||||||
|
|
@ -1344,7 +1399,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.
|
||||||
|
|
@ -1376,7 +1431,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;
|
||||||
|
|
@ -1451,7 +1506,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);
|
||||||
|
|
@ -1465,7 +1520,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
|
||||||
|
|
@ -3032,10 +3087,20 @@ 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._showLocalCursor && this._localCursors.empty)) {
|
||||||
// User does not want to see the dot, so...
|
// User does not want to see the dot or has no local cursor, so...
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (this._showLocalCursor) {
|
||||||
|
// Do not show the dot in states with a local cursor
|
||||||
|
if (this._viewportDragging) {
|
||||||
|
if (this._localCursors.dragging) { return false; }
|
||||||
|
} else if (this._dragViewport) {
|
||||||
|
if (this._localCursors.drag) { return false; }
|
||||||
|
} else if (this._viewOnly) {
|
||||||
|
if (this._localCursors.viewOnly) { return false; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The dot should not be shown if the cursor is already visible,
|
// The dot should not be shown if the cursor is already visible,
|
||||||
// i.e. contains at least one not-fully-transparent pixel.
|
// i.e. contains at least one not-fully-transparent pixel.
|
||||||
|
|
@ -3057,6 +3122,10 @@ export default class RFB extends EventTargetMixin {
|
||||||
this._rfbConnectionState !== "connected") {
|
this._rfbConnectionState !== "connected") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (this._showLocalCursor) {
|
||||||
|
this._refreshCursorWithLocalCursors();
|
||||||
|
return;
|
||||||
|
}
|
||||||
const image = this._shouldShowDotCursor() ? RFB.cursors.dot : this._cursorImage;
|
const image = this._shouldShowDotCursor() ? RFB.cursors.dot : this._cursorImage;
|
||||||
this._cursor.change(image.rgbaPixels,
|
this._cursor.change(image.rgbaPixels,
|
||||||
image.hotx, image.hoty,
|
image.hotx, image.hoty,
|
||||||
|
|
@ -3064,6 +3133,30 @@ export default class RFB extends EventTargetMixin {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_refreshCursorWithLocalCursors() {
|
||||||
|
let image = this._cursorImage;
|
||||||
|
let localCursor; // = 'none';
|
||||||
|
if (this._viewportDragging) {
|
||||||
|
localCursor = this._localCursors.dragging;
|
||||||
|
} else if (this._dragViewport) {
|
||||||
|
localCursor = this._localCursors.drag;
|
||||||
|
} else if (this._viewOnly) {
|
||||||
|
localCursor = this._localCursors.viewOnly;
|
||||||
|
// clear locally rendered cursor when switching to view-only whilst connected
|
||||||
|
image = RFB.cursors.none;
|
||||||
|
} else if (this._shouldShowDotCursor()) {
|
||||||
|
localCursor = this._localCursors.empty;
|
||||||
|
image = this._showDotCursor ? RFB.cursors.dot : this._cursorImage;
|
||||||
|
} else {
|
||||||
|
localCursor = this._localCursors.default;
|
||||||
|
}
|
||||||
|
this._cursor.change(image.rgbaPixels,
|
||||||
|
image.hotx, image.hoty,
|
||||||
|
image.w, image.h,
|
||||||
|
{ localCursor }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static genDES(password, challenge) {
|
static genDES(password, challenge) {
|
||||||
const passwordChars = password.split('').map(c => c.charCodeAt(0));
|
const passwordChars = password.split('').map(c => c.charCodeAt(0));
|
||||||
const key = legacyCrypto.importKey(
|
const key = legacyCrypto.importKey(
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,12 @@
|
||||||
|
|
||||||
import { supportsCursorURIs, isTouchDevice } from './browser.js';
|
import { supportsCursorURIs, isTouchDevice } from './browser.js';
|
||||||
|
|
||||||
const useFallback = !supportsCursorURIs || isTouchDevice;
|
// Sometimes (at least with Chrome and Firefox on Windows)
|
||||||
|
// isTouchDevice is true even if there is no touch device, in
|
||||||
|
// this case useFallback ist also true and cursor URIs are never
|
||||||
|
// used.
|
||||||
|
const __FORCE_NO_TOUCH_DEVICE__ = false;
|
||||||
|
const useFallback = !supportsCursorURIs || (!__FORCE_NO_TOUCH_DEVICE__ && isTouchDevice);
|
||||||
|
|
||||||
export default class Cursor {
|
export default class Cursor {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
@ -14,7 +19,7 @@ export default class Cursor {
|
||||||
|
|
||||||
this._canvas = document.createElement('canvas');
|
this._canvas = document.createElement('canvas');
|
||||||
|
|
||||||
if (useFallback) {
|
// always initalize canvas.style in case of showing local cursors
|
||||||
this._canvas.style.position = 'fixed';
|
this._canvas.style.position = 'fixed';
|
||||||
this._canvas.style.zIndex = '65535';
|
this._canvas.style.zIndex = '65535';
|
||||||
this._canvas.style.pointerEvents = 'none';
|
this._canvas.style.pointerEvents = 'none';
|
||||||
|
|
@ -24,7 +29,6 @@ export default class Cursor {
|
||||||
this._canvas.style.WebkitUserSelect = 'none';
|
this._canvas.style.WebkitUserSelect = 'none';
|
||||||
// Can't use "display" because of Firefox bug #1445997
|
// Can't use "display" because of Firefox bug #1445997
|
||||||
this._canvas.style.visibility = 'hidden';
|
this._canvas.style.visibility = 'hidden';
|
||||||
}
|
|
||||||
|
|
||||||
this._position = { x: 0, y: 0 };
|
this._position = { x: 0, y: 0 };
|
||||||
this._hotSpot = { x: 0, y: 0 };
|
this._hotSpot = { x: 0, y: 0 };
|
||||||
|
|
@ -37,14 +41,15 @@ export default class Cursor {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
attach(target) {
|
attach(target, { showLocalCursor } = {}) {
|
||||||
if (this._target) {
|
if (this._target) {
|
||||||
this.detach();
|
this.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
this._target = target;
|
this._target = target;
|
||||||
|
this._showLocalCursor = !!showLocalCursor;
|
||||||
|
|
||||||
if (useFallback) {
|
if (useFallback || this._showLocalCursor) {
|
||||||
document.body.appendChild(this._canvas);
|
document.body.appendChild(this._canvas);
|
||||||
|
|
||||||
const options = { capture: true, passive: true };
|
const options = { capture: true, passive: true };
|
||||||
|
|
@ -54,7 +59,7 @@ export default class Cursor {
|
||||||
this._target.addEventListener('mouseup', this._eventHandlers.mouseup, options);
|
this._target.addEventListener('mouseup', this._eventHandlers.mouseup, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.clear();
|
this.clear({ localCursor: showLocalCursor });
|
||||||
}
|
}
|
||||||
|
|
||||||
detach() {
|
detach() {
|
||||||
|
|
@ -62,7 +67,7 @@ export default class Cursor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useFallback) {
|
if (useFallback || this._showLocalCursor) {
|
||||||
const options = { capture: true, passive: true };
|
const options = { capture: true, passive: true };
|
||||||
this._target.removeEventListener('mouseover', this._eventHandlers.mouseover, options);
|
this._target.removeEventListener('mouseover', this._eventHandlers.mouseover, options);
|
||||||
this._target.removeEventListener('mouseleave', this._eventHandlers.mouseleave, options);
|
this._target.removeEventListener('mouseleave', this._eventHandlers.mouseleave, options);
|
||||||
|
|
@ -77,9 +82,9 @@ export default class Cursor {
|
||||||
this._target = null;
|
this._target = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
change(rgba, hotx, hoty, w, h) {
|
change(rgba, hotx, hoty, w, h, { localCursor } = {}) {
|
||||||
if ((w === 0) || (h === 0)) {
|
if ((w === 0) || (h === 0)) {
|
||||||
this.clear();
|
this.clear({ localCursor });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,7 +102,8 @@ export default class Cursor {
|
||||||
ctx.clearRect(0, 0, w, h);
|
ctx.clearRect(0, 0, w, h);
|
||||||
ctx.putImageData(img, 0, 0);
|
ctx.putImageData(img, 0, 0);
|
||||||
|
|
||||||
if (useFallback) {
|
if (useFallback || this._showLocalCursor) {
|
||||||
|
this._target.style.cursor = localCursor ?? 'none';
|
||||||
this._updatePosition();
|
this._updatePosition();
|
||||||
} else {
|
} else {
|
||||||
let url = this._canvas.toDataURL();
|
let url = this._canvas.toDataURL();
|
||||||
|
|
@ -105,8 +111,12 @@ export default class Cursor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear({ localCursor } = {}) {
|
||||||
this._target.style.cursor = 'none';
|
// whilst dragging the viewport and changes to the remote cursor
|
||||||
|
// are made the target might be detached
|
||||||
|
if (this._target) {
|
||||||
|
this._target.style.cursor = localCursor ?? '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;
|
||||||
|
|
@ -118,7 +128,7 @@ export default class 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) {
|
||||||
if (!useFallback) {
|
if (!useFallback && !this._showLocalCursor) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// clientX/clientY are relative the _visual viewport_,
|
// clientX/clientY are relative the _visual viewport_,
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,9 @@ Currently, the following options are available:
|
||||||
* `view_clip` - If the remote session should be clipped or use scrollbars if
|
* `view_clip` - If the remote session should be clipped or use scrollbars if
|
||||||
it cannot fit in the browser.
|
it cannot fit in the browser.
|
||||||
|
|
||||||
|
* `view_drag` - If the remote session is clipped enable dragging the viewport
|
||||||
|
when connected.
|
||||||
|
|
||||||
* `resize` - How to resize the remote session if it is not the same size as
|
* `resize` - How to resize the remote session if it is not the same size as
|
||||||
the browser window. Can be one of `off`, `scale` and `remote`.
|
the browser window. Can be one of `off`, `scale` and `remote`.
|
||||||
|
|
||||||
|
|
|
||||||
4
vnc.html
4
vnc.html
|
|
@ -227,6 +227,10 @@
|
||||||
Clip to window
|
Clip to window
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
|
<li style="display: none">
|
||||||
|
<!-- hidden checkbox to enable 'Move/Drag viewport' with url parameter -->
|
||||||
|
<input id="noVNC_setting_view_drag" type="checkbox">
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label for="noVNC_setting_resize">Scaling mode:</label>
|
<label for="noVNC_setting_resize">Scaling mode:</label>
|
||||||
<select id="noVNC_setting_resize" name="vncResize">
|
<select id="noVNC_setting_resize" name="vncResize">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue