-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Show local cursor while dragging the viewport #1992
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
6eb28b8
355dd27
0f48f31
5782915
97c0ad4
abc7d63
254fff9
59e40b4
b1745d5
5a9a81c
4dd16ad
b5b7ebe
3b79d45
68a2db4
4fc3fc9
702302f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -233,6 +233,14 @@ export default class RFB extends EventTargetMixin { | |
|
|
||
| // 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 | ||
| // 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 ===== | ||
|
|
||
| this.dragViewport = false; | ||
| this.focusOnClick = true; | ||
|
|
||
| this._viewOnly = false; | ||
| this._clipViewport = false; | ||
| this._clippingViewport = false; | ||
| this._dragViewport = false; | ||
| this._scaleViewport = false; | ||
| this._resizeSession = false; | ||
|
|
||
|
|
@@ -315,8 +323,10 @@ export default class RFB extends EventTargetMixin { | |
| this._rfbConnectionState === "connected") { | ||
| if (viewOnly) { | ||
| this._keyboard.ungrab(); | ||
| this._refreshCursor(); | ||
| } else { | ||
| this._keyboard.grab(); | ||
| this._refreshCursor(); | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -342,6 +352,12 @@ export default class RFB extends EventTargetMixin { | |
| this._updateClip(); | ||
| } | ||
|
|
||
| get dragViewport() { return this._dragViewport; } | ||
| set dragViewport(dragViewport) { | ||
| this._dragViewport = dragViewport; | ||
| this._refreshCursor(); | ||
| } | ||
|
|
||
| get scaleViewport() { return this._scaleViewport; } | ||
| set scaleViewport(scale) { | ||
| this._scaleViewport = scale; | ||
|
|
@@ -370,6 +386,29 @@ export default class RFB extends EventTargetMixin { | |
| 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; } | ||
| set background(cssValue) { this._screen.style.background = cssValue; } | ||
|
|
||
|
|
@@ -574,7 +613,9 @@ export default class RFB extends EventTargetMixin { | |
|
|
||
| this._gestures.attach(this._canvas); | ||
|
|
||
| this._cursor.attach(this._canvas); | ||
| this._cursor.attach(this._canvas, { | ||
| showLocalCursor: this._showLocalCursor | ||
| }); | ||
| this._refreshCursor(); | ||
|
|
||
| // Monitor size changes of the screen element | ||
|
|
@@ -1111,16 +1152,23 @@ export default class RFB extends EventTargetMixin { | |
|
|
||
| let bmask = RFB._convertButtonMask(ev.buttons); | ||
|
|
||
| let down = ev.type == 'mousedown'; | ||
| let down = false; | ||
|
Comment on lines
1114
to
+1155
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does this improve?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a minor non-functional optimization. First, the event type is compared against the word As the commit message says: Do not compare to 'mousedown' on every 'mousemove'. I guess --- 0f48f31e08a70045e4fe5deebcac7d7b04fd816d/core/rfb.js
+++ 57829159839e7a2358f5c22a53414565f5704087/core/rfb.js
@@ -1117,11 +1117,9 @@ export default class RFB extends EventTargetMixin {
let bmask = RFB._convertButtonMask(ev.buttons);
+ let down = false;
- let down = ev.type == 'mousedown';
switch (ev.type) {
case 'mousedown':
+ down = true;
+ // eslint-disable-next-line no-fallthrough
case 'mouseup':
if (this._dragViewport) {
this._cursor.setLocalCursor(down ? 'grabbing' : 'grab');
@@ -1157 +1159 @@
break;
case 'mousemove': |
||
| switch (ev.type) { | ||
| case 'mousedown': | ||
| down = true; | ||
| // eslint-disable-next-line no-fallthrough | ||
| case 'mouseup': | ||
| if (this.dragViewport) { | ||
| if (this._dragViewport) { | ||
| if (down && !this._viewportDragging) { | ||
| this._viewportDragging = true; | ||
| this._viewportDragPos = {'x': pos.x, 'y': pos.y}; | ||
| this._viewportHasMoved = false; | ||
|
|
||
| if (this._showLocalCursor) { | ||
| this._refreshCursor(); | ||
| this._cursor.detach(); | ||
| } | ||
|
|
||
| this._flushMouseMoveTimer(pos.x, pos.y); | ||
|
|
||
| // Skip sending mouse events, instead save the current | ||
|
|
@@ -1130,6 +1178,13 @@ export default class RFB extends EventTargetMixin { | |
| } else { | ||
| 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 | ||
| // here and should not send any mouse events | ||
| if (this._viewportHasMoved) { | ||
|
|
@@ -1334,7 +1389,7 @@ export default class RFB extends EventTargetMixin { | |
| this._handleTapEvent(ev, 0x2); | ||
| break; | ||
| case 'drag': | ||
| if (this.dragViewport) { | ||
| if (this._dragViewport) { | ||
| this._viewportHasMoved = false; | ||
| this._viewportDragging = true; | ||
| this._viewportDragPos = {'x': pos.x, 'y': pos.y}; | ||
|
|
@@ -1344,7 +1399,7 @@ export default class RFB extends EventTargetMixin { | |
| } | ||
| break; | ||
| case 'longpress': | ||
| if (this.dragViewport) { | ||
| if (this._dragViewport) { | ||
| // If dragViewport is true, we need to wait to see | ||
| // if we have dragged outside the threshold before | ||
| // sending any events to the server. | ||
|
|
@@ -1376,7 +1431,7 @@ export default class RFB extends EventTargetMixin { | |
| break; | ||
| case 'drag': | ||
| case 'longpress': | ||
| if (this.dragViewport) { | ||
| if (this._dragViewport) { | ||
| this._viewportDragging = true; | ||
| const deltaX = this._viewportDragPos.x - pos.x; | ||
| const deltaY = this._viewportDragPos.y - pos.y; | ||
|
|
@@ -1451,7 +1506,7 @@ export default class RFB extends EventTargetMixin { | |
| case 'twodrag': | ||
| break; | ||
| case 'drag': | ||
| if (this.dragViewport) { | ||
| if (this._dragViewport) { | ||
| this._viewportDragging = false; | ||
| } else { | ||
| this._fakeMouseMove(ev, pos.x, pos.y); | ||
|
|
@@ -1465,7 +1520,7 @@ export default class RFB extends EventTargetMixin { | |
| break; | ||
| } | ||
|
|
||
| if (this.dragViewport && !this._viewportHasMoved) { | ||
| if (this._dragViewport && !this._viewportHasMoved) { | ||
| this._fakeMouseMove(ev, pos.x, pos.y); | ||
| // If dragViewport is true, we need to wait to see | ||
| // if we have dragged outside the threshold before | ||
|
|
@@ -3032,10 +3087,20 @@ export default class RFB extends EventTargetMixin { | |
|
|
||
| _shouldShowDotCursor() { | ||
| // Called when this._cursorImage is updated | ||
| if (!this._showDotCursor) { | ||
| // User does not want to see the dot, so... | ||
| if (!this._showDotCursor && !(this._showLocalCursor && this._localCursors.empty)) { | ||
| // User does not want to see the dot or has no local cursor, so... | ||
| 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, | ||
| // i.e. contains at least one not-fully-transparent pixel. | ||
|
|
@@ -3057,13 +3122,41 @@ export default class RFB extends EventTargetMixin { | |
| this._rfbConnectionState !== "connected") { | ||
| return; | ||
| } | ||
| if (this._showLocalCursor) { | ||
| this._refreshCursorWithLocalCursors(); | ||
| return; | ||
| } | ||
| const image = this._shouldShowDotCursor() ? RFB.cursors.dot : this._cursorImage; | ||
| this._cursor.change(image.rgbaPixels, | ||
| image.hotx, image.hoty, | ||
| image.w, image.h | ||
| ); | ||
| } | ||
|
|
||
| _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) { | ||
| const passwordChars = password.split('').map(c => c.charCodeAt(0)); | ||
| const key = legacyCrypto.importKey( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have the toolbar button for this. What's the purpose of this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a button, but no URL parameter to save this setting as bookmark or enable it automatically when embedding.
https://example.org/vnc.html?autoconnect=1&view_clip=1&view_drag=1Nevertheless, it wasn't working as intended. Fixed with abc7d63