Merge e34a1c2354 into fc5b83c08f
This commit is contained in:
commit
f97e257a59
|
|
@ -22,6 +22,7 @@ export const encodings = {
|
|||
pseudoEncodingQualityLevel0: -32,
|
||||
pseudoEncodingDesktopSize: -223,
|
||||
pseudoEncodingLastRect: -224,
|
||||
pseudoEncodingPointerPos: -232,
|
||||
pseudoEncodingCursor: -239,
|
||||
pseudoEncodingQEMUExtendedKeyEvent: -258,
|
||||
pseudoEncodingQEMULedEvent: -261,
|
||||
|
|
|
|||
15
core/rfb.js
15
core/rfb.js
|
|
@ -314,7 +314,7 @@ export default class RFB extends EventTargetMixin {
|
|||
|
||||
get viewOnly() { return this._viewOnly; }
|
||||
set viewOnly(viewOnly) {
|
||||
this._viewOnly = viewOnly;
|
||||
this._viewOnly = this._cursor.viewOnly = viewOnly;
|
||||
|
||||
if (this._rfbConnectionState === "connecting" ||
|
||||
this._rfbConnectionState === "connected") {
|
||||
|
|
@ -2261,6 +2261,7 @@ export default class RFB extends EventTargetMixin {
|
|||
|
||||
encs.push(encodings.pseudoEncodingDesktopSize);
|
||||
encs.push(encodings.pseudoEncodingLastRect);
|
||||
encs.push(encodings.pseudoEncodingPointerPos);
|
||||
encs.push(encodings.pseudoEncodingQEMUExtendedKeyEvent);
|
||||
encs.push(encodings.pseudoEncodingQEMULedEvent);
|
||||
encs.push(encodings.pseudoEncodingExtendedDesktopSize);
|
||||
|
|
@ -2711,6 +2712,9 @@ export default class RFB extends EventTargetMixin {
|
|||
case encodings.pseudoEncodingQEMULedEvent:
|
||||
return this._handleLedEvent();
|
||||
|
||||
case encodings.pseudoEncodingPointerPos:
|
||||
return this._handlePointerPos();
|
||||
|
||||
default:
|
||||
return this._handleDataRect();
|
||||
}
|
||||
|
|
@ -2903,6 +2907,15 @@ export default class RFB extends EventTargetMixin {
|
|||
return true;
|
||||
}
|
||||
|
||||
_handlePointerPos() {
|
||||
const x = this._FBU.x;
|
||||
const y = this._FBU.y;
|
||||
|
||||
this._cursor.moveRemote(x, y, this._display.scale);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_handleExtendedDesktopSize() {
|
||||
if (this._sock.rQwait("ExtendedDesktopSize", 4)) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -14,17 +14,15 @@ export default class Cursor {
|
|||
|
||||
this._canvas = document.createElement('canvas');
|
||||
|
||||
if (useFallback) {
|
||||
this._canvas.style.position = 'fixed';
|
||||
this._canvas.style.zIndex = '65535';
|
||||
this._canvas.style.pointerEvents = 'none';
|
||||
// Safari on iOS can select the cursor image
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=249223
|
||||
this._canvas.style.userSelect = 'none';
|
||||
this._canvas.style.WebkitUserSelect = 'none';
|
||||
// Can't use "display" because of Firefox bug #1445997
|
||||
this._canvas.style.visibility = 'hidden';
|
||||
}
|
||||
this._canvas.style.position = 'fixed';
|
||||
this._canvas.style.zIndex = '65535';
|
||||
this._canvas.style.pointerEvents = 'none';
|
||||
// Safari on iOS can select the cursor image
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=249223
|
||||
this._canvas.style.userSelect = 'none';
|
||||
this._canvas.style.WebkitUserSelect = 'none';
|
||||
// Can't use "display" because of Firefox bug #1445997
|
||||
this._canvas.style.visibility = 'hidden';
|
||||
|
||||
this._position = { x: 0, y: 0 };
|
||||
this._hotSpot = { x: 0, y: 0 };
|
||||
|
|
@ -35,6 +33,20 @@ export default class Cursor {
|
|||
'mousemove': this._handleMouseMove.bind(this),
|
||||
'mouseup': this._handleMouseUp.bind(this),
|
||||
};
|
||||
|
||||
this._mouseOver = false;
|
||||
this._viewOnly = false;
|
||||
}
|
||||
|
||||
get viewOnly() { return this._viewOnly; }
|
||||
set viewOnly(viewOnly) {
|
||||
if (viewOnly !== this._viewOnly) {
|
||||
this._viewOnly = viewOnly;
|
||||
this._resetNativeCursorStyle();
|
||||
if (this._viewOnly) {
|
||||
this._showCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
attach(target) {
|
||||
|
|
@ -44,12 +56,13 @@ export default class Cursor {
|
|||
|
||||
this._target = target;
|
||||
|
||||
if (useFallback) {
|
||||
document.body.appendChild(this._canvas);
|
||||
document.body.appendChild(this._canvas);
|
||||
|
||||
const options = { capture: true, passive: true };
|
||||
this._target.addEventListener('mouseover', this._eventHandlers.mouseover, options);
|
||||
this._target.addEventListener('mouseleave', this._eventHandlers.mouseleave, options);
|
||||
const options = { capture: true, passive: true };
|
||||
this._target.addEventListener('mouseover', this._eventHandlers.mouseover, options);
|
||||
this._target.addEventListener('mouseleave', this._eventHandlers.mouseleave, options);
|
||||
|
||||
if (useFallback) {
|
||||
this._target.addEventListener('mousemove', this._eventHandlers.mousemove, options);
|
||||
this._target.addEventListener('mouseup', this._eventHandlers.mouseup, options);
|
||||
}
|
||||
|
|
@ -62,16 +75,17 @@ export default class Cursor {
|
|||
return;
|
||||
}
|
||||
|
||||
const options = { capture: true, passive: true };
|
||||
this._target.removeEventListener('mouseover', this._eventHandlers.mouseover, options);
|
||||
this._target.removeEventListener('mouseleave', this._eventHandlers.mouseleave, options);
|
||||
|
||||
if (useFallback) {
|
||||
const options = { capture: true, passive: true };
|
||||
this._target.removeEventListener('mouseover', this._eventHandlers.mouseover, options);
|
||||
this._target.removeEventListener('mouseleave', this._eventHandlers.mouseleave, options);
|
||||
this._target.removeEventListener('mousemove', this._eventHandlers.mousemove, options);
|
||||
this._target.removeEventListener('mouseup', this._eventHandlers.mouseup, options);
|
||||
}
|
||||
|
||||
if (document.contains(this._canvas)) {
|
||||
document.body.removeChild(this._canvas);
|
||||
}
|
||||
if (document.contains(this._canvas)) {
|
||||
document.body.removeChild(this._canvas);
|
||||
}
|
||||
|
||||
this._target = null;
|
||||
|
|
@ -97,16 +111,17 @@ export default class Cursor {
|
|||
ctx.clearRect(0, 0, w, h);
|
||||
ctx.putImageData(img, 0, 0);
|
||||
|
||||
if (useFallback) {
|
||||
if (useFallback || this._viewOnly || !this._mouseOver) {
|
||||
this._updatePosition();
|
||||
} else {
|
||||
}
|
||||
if (!useFallback && !this._viewOnly) {
|
||||
let url = this._canvas.toDataURL();
|
||||
this._target.style.cursor = 'url(' + url + ')' + hotx + ' ' + hoty + ', default';
|
||||
}
|
||||
}
|
||||
|
||||
clear() {
|
||||
this._target.style.cursor = 'none';
|
||||
this._resetNativeCursorStyle();
|
||||
this._canvas.width = 0;
|
||||
this._canvas.height = 0;
|
||||
this._position.x = this._position.x + this._hotSpot.x;
|
||||
|
|
@ -115,6 +130,12 @@ export default class Cursor {
|
|||
this._hotSpot.y = 0;
|
||||
}
|
||||
|
||||
_resetNativeCursorStyle() {
|
||||
if (this._target) {
|
||||
this._target.style.cursor = this._viewOnly ? 'not-allowed' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Mouse events might be emulated, this allows
|
||||
// moving the cursor in such cases
|
||||
move(clientX, clientY) {
|
||||
|
|
@ -136,19 +157,58 @@ export default class Cursor {
|
|||
this._updateVisibility(target);
|
||||
}
|
||||
|
||||
moveRemote(remoteX, remoteY, scale) {
|
||||
if (this._mouseOver && !this._viewOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
let targetBounds = this._target.getBoundingClientRect();
|
||||
this._position.x = targetBounds.left + remoteX * scale - this._hotSpot.x;
|
||||
this._position.y = targetBounds.top + remoteY * scale - this._hotSpot.y;
|
||||
|
||||
this._updatePosition();
|
||||
}
|
||||
|
||||
_handleMouseOver(event) {
|
||||
// This event could be because we're entering the target, or
|
||||
// moving around amongst its sub elements. Let the move handler
|
||||
// sort things out.
|
||||
this._mouseOver = true;
|
||||
this._handleMouseMove(event);
|
||||
}
|
||||
|
||||
_handleMouseLeave(event) {
|
||||
if (this._viewOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
let targetBounds = this._getVisibleBoundingRect(this._target);
|
||||
this._mouseOver = event.clientX >= targetBounds.left && event.clientX < targetBounds.right &&
|
||||
event.clientY >= targetBounds.top && event.clientY < targetBounds.bottom;
|
||||
// Check if we should show the cursor on the element we are leaving to
|
||||
this._updateVisibility(event.relatedTarget);
|
||||
}
|
||||
|
||||
_getVisibleBoundingRect(element) {
|
||||
let rect = element.getBoundingClientRect();
|
||||
let bounds = { left: rect.left, top: rect.top, right: rect.right, bottom: rect.bottom };
|
||||
if (element.parentElement) {
|
||||
let parentBounds = element.parentElement.getBoundingClientRect();
|
||||
bounds = {
|
||||
left: Math.max(bounds.left, parentBounds.left),
|
||||
top: Math.max(bounds.top, parentBounds.top),
|
||||
right: Math.min(bounds.right, parentBounds.right),
|
||||
bottom: Math.min(bounds.bottom, parentBounds.bottom)
|
||||
};
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
||||
_handleMouseMove(event) {
|
||||
if (this._viewOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._updateVisibility(event.target);
|
||||
|
||||
this._position.x = event.clientX - this._hotSpot.x;
|
||||
|
|
@ -158,6 +218,10 @@ export default class Cursor {
|
|||
}
|
||||
|
||||
_handleMouseUp(event) {
|
||||
if (this._viewOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We might get this event because of a drag operation that
|
||||
// moved outside of the target. Check what's under the cursor
|
||||
// now and adjust visibility based on that.
|
||||
|
|
@ -230,7 +294,7 @@ export default class Cursor {
|
|||
if (this._captureIsActive()) {
|
||||
target = document.captureElement;
|
||||
}
|
||||
if (this._shouldShowCursor(target)) {
|
||||
if (!this._mouseOver || (useFallback && this._shouldShowCursor(target))) {
|
||||
this._showCursor();
|
||||
} else {
|
||||
this._hideCursor();
|
||||
|
|
|
|||
Loading…
Reference in New Issue