Add support for forward and back mouse buttons

This commit implements the extendedMouseButtons pseudo-encoding, which
makes it possible to use the forward and back mouse buttons.
This commit is contained in:
Adam Halim
2025-01-09 09:19:21 +01:00
parent e8602f23ab
commit e081d1415a
3 changed files with 96 additions and 4 deletions

View File

@@ -30,6 +30,7 @@ export const encodings = {
pseudoEncodingXvp: -309,
pseudoEncodingFence: -312,
pseudoEncodingContinuousUpdates: -313,
pseudoEncodingExtendedMouseButtons: -316,
pseudoEncodingCompressLevel9: -247,
pseudoEncodingCompressLevel0: -256,
pseudoEncodingVMwareCursor: 0x574d5664,

View File

@@ -152,6 +152,8 @@ export default class RFB extends EventTargetMixin {
this._qemuExtKeyEventSupported = false;
this._extendedPointerEventSupported = false;
this._clipboardText = null;
this._clipboardServerCapabilitiesActions = {};
this._clipboardServerCapabilitiesFormats = {};
@@ -1051,10 +1053,11 @@ export default class RFB extends EventTargetMixin {
1: 1 << 2, // Right
2: 1 << 1, // Middle
3: 1 << 7, // Back
4: 1 << 8, // Forward
};
let bmask = 0;
for (let i = 0; i < 4; i++) {
for (let i = 0; i < 5; i++) {
if (buttons & (1 << i)) {
bmask |= buttonMaskMap[i];
}
@@ -1189,8 +1192,20 @@ export default class RFB extends EventTargetMixin {
if (this._rfbConnectionState !== 'connected') { return; }
if (this._viewOnly) { return; } // View only, skip mouse events
RFB.messages.pointerEvent(this._sock, this._display.absX(x),
this._display.absY(y), mask);
// Highest bit in mask is never sent to the server
if (mask & 0x8000) {
throw new Error("Illegal mouse button mask (mask: " + mask + ")");
}
let extendedMouseButtons = mask & 0x7f80;
if (this._extendedPointerEventSupported && extendedMouseButtons) {
RFB.messages.extendedPointerEvent(this._sock, this._display.absX(x),
this._display.absY(y), mask);
} else {
RFB.messages.pointerEvent(this._sock, this._display.absX(x),
this._display.absY(y), mask);
}
}
_handleWheel(ev) {
@@ -2229,6 +2244,7 @@ export default class RFB extends EventTargetMixin {
encs.push(encodings.pseudoEncodingContinuousUpdates);
encs.push(encodings.pseudoEncodingDesktopName);
encs.push(encodings.pseudoEncodingExtendedClipboard);
encs.push(encodings.pseudoEncodingExtendedMouseButtons);
if (this._fbDepth == 24) {
encs.push(encodings.pseudoEncodingVMwareCursor);
@@ -2658,6 +2674,10 @@ export default class RFB extends EventTargetMixin {
case encodings.pseudoEncodingExtendedDesktopSize:
return this._handleExtendedDesktopSize();
case encodings.pseudoEncodingExtendedMouseButtons:
this._extendedPointerEventSupported = true;
return true;
case encodings.pseudoEncodingQEMULedEvent:
return this._handleLedEvent();
@@ -3067,6 +3087,10 @@ RFB.messages = {
pointerEvent(sock, x, y, mask) {
sock.sQpush8(5); // msg-type
// Marker bit must be set to 0, otherwise the server might
// confuse the marker bit with the highest bit in a normal
// PointerEvent message.
mask = mask & 0x7f;
sock.sQpush8(mask);
sock.sQpush16(x);
@@ -3075,6 +3099,27 @@ RFB.messages = {
sock.flush();
},
extendedPointerEvent(sock, x, y, mask) {
sock.sQpush8(5); // msg-type
let higherBits = (mask >> 7) & 0xff;
// Bits 2-7 are reserved
if (higherBits & 0xfc) {
throw new Error("Invalid mouse button mask: " + mask);
}
let lowerBits = mask & 0x7f;
lowerBits |= 0x80; // Set marker bit to 1
sock.sQpush8(lowerBits);
sock.sQpush16(x);
sock.sQpush16(y);
sock.sQpush8(higherBits);
sock.flush();
},
// Used to build Notify and Request data.
_buildExtendedClipboardFlags(actions, formats) {
let data = new Uint8Array(4);