Mouse button mapping (JS -> Xorg) support

This commit is contained in:
Dmitry Maksyoma 2022-10-06 18:30:18 +13:00
parent 8bc91a4ef2
commit af0484ab42
3 changed files with 71 additions and 2 deletions

View File

@ -41,6 +41,7 @@ import KeyTable from "../core/input/keysym.js";
import keysyms from "../core/input/keysymdef.js";
import Keyboard from "../core/input/keyboard.js";
import RFB from "../core/rfb.js";
import MouseButtonMapper from "../core/mousebuttonmapper.js";
import * as WebUtil from "./webutil.js";
const PAGE_TITLE = "KasmVNC";
@ -264,6 +265,21 @@ const UI = {
UI.setupSettingLabels();
UI.updateQuality();
},
initMouseButtonMapper() {
const mouseButtonMapper = new MouseButtonMapper();
const settings = WebUtil.readSetting("mouseButtonMapper");
if (settings) {
mouseButtonMapper.load(settings);
return mouseButtonMapper;
}
mouseButtonMapper.set(3, 7);
mouseButtonMapper.set(4, 8);
WebUtil.writeSetting("mouseButtonMapper", mouseButtonMapper.dump());
return mouseButtonMapper;
},
// Adds a link to the label elements on the corresponding input elements
setupSettingLabels() {
const labels = document.getElementsByTagName('LABEL');
@ -1381,6 +1397,7 @@ const UI = {
UI.rfb.keyboard.enableIME = UI.getSetting('enable_ime');
UI.rfb.clipboardBinary = supportsBinaryClipboard() && UI.rfb.clipboardSeamless;
UI.rfb.enableWebRTC = UI.getSetting('enable_webrtc');
UI.rfb.mouseButtonMapper = UI.initMouseButtonMapper();
//Only explicitly request permission to clipboard on browsers that support binary clipboard access
if (supportsBinaryClipboard()) {

49
core/mousebuttonmapper.js Normal file
View File

@ -0,0 +1,49 @@
export default class MouseButtonMapper {
constructor() {
this.map = new Map();
}
get(mouseButton) {
if (!this.map.has(mouseButton)) {
return mouseButton;
}
return this.map.get(mouseButton);
}
set(mouseButton, xorgMouseButton) {
return this.map.set(mouseButton, xorgMouseButton);
}
delete(mouseButton) {
return this.map.delete(mouseButton);
}
dump() {
return JSON.stringify(this.map, this._replacer);
}
load(json) {
this.map = JSON.parse(json, this._reviver);
}
_replacer(key, value) {
if (!(value instanceof Map)) {
return value;
}
return {
dataType: 'Map',
value: Array.from(value.entries())
};
}
_reviver(key, value) {
if (typeof value === 'object' && value !== null) {
if (value.dataType === 'Map') {
return new Map(value.value);
}
}
return value;
}
}

View File

@ -26,6 +26,7 @@ import DES from "./des.js";
import KeyTable from "./input/keysym.js";
import XtScancode from "./input/xtscancodes.js";
import { encodings } from "./encodings.js";
import MouseButtonMapper from "./mousebuttonmapper.js";
import RawDecoder from "./decoders/raw.js";
import CopyRectDecoder from "./decoders/copyrect.js";
@ -192,6 +193,7 @@ export default class RFB extends EventTargetMixin {
this._viewportHasMoved = false;
this._accumulatedWheelDeltaX = 0;
this._accumulatedWheelDeltaY = 0;
this.mouseButtonMapper = new MouseButtonMapper();
// Gesture state
this._gestureLastTapTime = null;
@ -1558,6 +1560,7 @@ export default class RFB extends EventTargetMixin {
this._canvas);
}
const mappedButton = this.mouseButtonMapper.get(ev.button);
switch (ev.type) {
case 'mousedown':
setCapture(this._canvas);
@ -1575,11 +1578,11 @@ export default class RFB extends EventTargetMixin {
this.checkLocalClipboard();
this._handleMouseButton(pos.x, pos.y,
true, 1 << ev.button);
true, 1 << mappedButton);
break;
case 'mouseup':
this._handleMouseButton(pos.x, pos.y,
false, 1 << ev.button);
false, 1 << mappedButton);
break;
case 'mousemove':
this._handleMouseMove(pos.x, pos.y);