improve design and add right click support
This commit is contained in:
parent
c573e750eb
commit
7fb4e97f9e
2 changed files with 94 additions and 24 deletions
7
capybara
7
capybara
|
@ -69,6 +69,10 @@ class InputController():
|
||||||
self.parser.add_handler("u", {
|
self.parser.add_handler("u", {
|
||||||
"button": "int"
|
"button": "int"
|
||||||
})
|
})
|
||||||
|
# Mouse button click
|
||||||
|
self.parser.add_handler("c", {
|
||||||
|
"button": "int"
|
||||||
|
})
|
||||||
def button_code_to_object(self, button_code: int):
|
def button_code_to_object(self, button_code: int):
|
||||||
# HACK
|
# HACK
|
||||||
obj = None
|
obj = None
|
||||||
|
@ -92,6 +96,9 @@ class InputController():
|
||||||
elif code == "u":
|
elif code == "u":
|
||||||
print("u", args["button"])
|
print("u", args["button"])
|
||||||
self.mouse_controller.release(self.button_code_to_object(args["button"]))
|
self.mouse_controller.release(self.button_code_to_object(args["button"]))
|
||||||
|
elif code == "c":
|
||||||
|
print("c", args["button"])
|
||||||
|
self.mouse_controller.click(self.button_code_to_object(args["button"]))
|
||||||
elif code == "s":
|
elif code == "s":
|
||||||
print("s", args["x"], args["y"])
|
print("s", args["x"], args["y"])
|
||||||
self.mouse_controller.scroll(args["x"], args["y"])
|
self.mouse_controller.scroll(args["x"], args["y"])
|
||||||
|
|
|
@ -6,8 +6,13 @@
|
||||||
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"> <title>Document</title>
|
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"> <title>Document</title>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const domlog = message => document.body.appendChild(document.createTextNode(message));
|
||||||
|
|
||||||
|
window.onerror = e => domlog(` ERROR - ${e} `);
|
||||||
|
|
||||||
const HOLDING_THRESHOLD_MS = 300;
|
const HOLDING_THRESHOLD_MS = 300;
|
||||||
const SINGLE_CLICK_BUTTON_UP_MS = 5;
|
|
||||||
const SCROLL_X_DAMPENING = 0.05;
|
const SCROLL_X_DAMPENING = 0.05;
|
||||||
const SCROLL_Y_DAMPENING = 0.06;
|
const SCROLL_Y_DAMPENING = 0.06;
|
||||||
|
|
||||||
|
@ -59,11 +64,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
class Connection {
|
class Connection {
|
||||||
constructor(url, logMessages=false) {
|
constructor(url) {
|
||||||
this.ws = null;
|
this.ws = null;
|
||||||
this.log = Logger(["Connection"], ["log"]).log;
|
this.log = Logger(["Connection"], ["log"]).log;
|
||||||
this.messageLog = Logger(["Connection", "Message"], ["log"]).log;
|
this.messageLog = Logger(["Connection", "Message"], ["log"]).log;
|
||||||
this.logMessages = logMessages;
|
|
||||||
this.url = url;
|
this.url = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +91,6 @@
|
||||||
else
|
else
|
||||||
message += param + ";";
|
message += param + ";";
|
||||||
});
|
});
|
||||||
if (this.logMessages) this.messageLog(message);
|
|
||||||
|
|
||||||
this.ws.send(message);
|
this.ws.send(message);
|
||||||
return message;
|
return message;
|
||||||
|
@ -120,16 +123,29 @@
|
||||||
return buttonCode;
|
return buttonCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// takes a gesture name and a touch list
|
||||||
|
// adds the gesture name to the touch and returns false if that touch already had that gesture
|
||||||
|
_gesture(gestureName, touchList) {
|
||||||
|
for (let i = 0; i < touchList.length; i++) {
|
||||||
|
const touch = this.ongoingTouches[touchList[i].identifier];
|
||||||
|
if (touch.gestured.includes(gestureName)) return false;
|
||||||
|
touch.gestured.push(gestureName);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
_sendRelativeMouseMovement(dx, dy) {
|
_sendRelativeMouseMovement(dx, dy) {
|
||||||
if (dx === 0 && dy === 0)
|
if (dx === 0 && dy === 0)
|
||||||
return;
|
return false;
|
||||||
this.connection.sendMessage("r", [dx, dy]);
|
this.connection.sendMessage("r", [dx, dy]);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_sendRelativeMouseScroll(dx, dy) {
|
_sendRelativeMouseScroll(dx, dy) {
|
||||||
if (dx === 0 && dy === 0)
|
if (dx === 0 && dy === 0)
|
||||||
return;
|
return false;
|
||||||
this.connection.sendMessage("s", [dx, dy]);
|
this.connection.sendMessage("s", [dx, dy]);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_sendMouseButtonDown(button="left") {
|
_sendMouseButtonDown(button="left") {
|
||||||
|
@ -141,11 +157,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
_sendSingleClick(button="left") {
|
_sendSingleClick(button="left") {
|
||||||
this._sendMouseButtonDown(button);
|
this.connection.sendMessage("c", [this.getButtonCode(button)]);
|
||||||
setTimeout(
|
|
||||||
() => this._sendMouseButtonUp(button),
|
|
||||||
SINGLE_CLICK_BUTTON_UP_MS
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bindTo(element) {
|
bindTo(element) {
|
||||||
|
@ -155,11 +167,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
onTouchMove(event) {
|
onTouchMove(event) {
|
||||||
const touches = event.touches;
|
const touches = event.changedTouches;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
for (let i = 0; i < touches.length; i++) {
|
event.stopPropagation();
|
||||||
this.ongoingTouches[touches[i].identifier].hasMoved = true;
|
|
||||||
}
|
|
||||||
const targetTouch = touches[0];
|
const targetTouch = touches[0];
|
||||||
|
|
||||||
this.currentMoveX = targetTouch.pageX;
|
this.currentMoveX = targetTouch.pageX;
|
||||||
|
@ -178,28 +189,53 @@
|
||||||
this.lastMoveX = this.currentMoveX;
|
this.lastMoveX = this.currentMoveX;
|
||||||
this.lastMoveY = this.currentMoveY;
|
this.lastMoveY = this.currentMoveY;
|
||||||
// if two touches moved at the same time, assume scrolling intent
|
// if two touches moved at the same time, assume scrolling intent
|
||||||
|
|
||||||
|
// if _sendRelativeMouseScroll or _sendRelativeMouseMovement return true, it means that the delta values are non-zero and a packet has been sent to the server
|
||||||
|
// in that case, the touches will be marked as moved
|
||||||
|
let shouldMarkTouchesAsMoved = false;
|
||||||
if (touches.length === 2) {
|
if (touches.length === 2) {
|
||||||
this._sendRelativeMouseScroll(deltaX * SCROLL_X_DAMPENING, deltaY * SCROLL_Y_DAMPENING);
|
if (
|
||||||
|
this._sendRelativeMouseScroll(deltaX * SCROLL_X_DAMPENING, deltaY * SCROLL_Y_DAMPENING)
|
||||||
|
) {
|
||||||
|
shouldMarkTouchesAsMoved = true;
|
||||||
|
}
|
||||||
|
} else if (touches.length === 3 && this._gesture("GESTURE_RIGHT_CLICK", touches)) {
|
||||||
|
shouldMarkTouchesAsMoved = true;
|
||||||
|
this._sendSingleClick("right");
|
||||||
} else {
|
} else {
|
||||||
this._sendRelativeMouseMovement(deltaX, deltaY);
|
if (
|
||||||
|
this._sendRelativeMouseMovement(deltaX, deltaY)
|
||||||
|
) {
|
||||||
|
shouldMarkTouchesAsMoved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shouldMarkTouchesAsMoved) {
|
||||||
|
for (let i = 0; i < touches.length; i++) {
|
||||||
|
this.ongoingTouches[touches[i].identifier].hasMoved = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onTouchEnd(event) {
|
onTouchEnd(event) {
|
||||||
const changedTouches = event.changedTouches;
|
const changedTouches = event.changedTouches;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
this.shouldResetLastMove = true;
|
this.shouldResetLastMove = true;
|
||||||
|
|
||||||
if (changedTouches.length === 1) {
|
if (changedTouches.length === 1) {
|
||||||
// This is a single tap - left click
|
// This is a single tap - left click
|
||||||
if (!this.ongoingTouches[changedTouches[0].identifier].hasMoved) {
|
if (!this.ongoingTouches[changedTouches[0].identifier].hasMoved) {
|
||||||
this._sendSingleClick("left");
|
this._sendSingleClick("left");
|
||||||
// We were in "holding mode" and now that touch event has ended,
|
|
||||||
// thus we have to stop holding the left click button
|
// We were in "holding mode" and now that touch event has ended,
|
||||||
|
// thus we have to stop holding the left click button
|
||||||
} else if (this.isInHoldingMode) {
|
} else if (this.isInHoldingMode) {
|
||||||
this._sendMouseButtonUp("left");
|
this._sendMouseButtonUp("left");
|
||||||
this.isInHoldingMode = false;
|
this.isInHoldingMode = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove all ended touches
|
||||||
for (let i = 0; i < changedTouches.length; i++) {
|
for (let i = 0; i < changedTouches.length; i++) {
|
||||||
const touch = changedTouches[i];
|
const touch = changedTouches[i];
|
||||||
this.ongoingTouches[touch.identifier] = null;
|
this.ongoingTouches[touch.identifier] = null;
|
||||||
|
@ -210,6 +246,7 @@
|
||||||
onTouchStart(event) {
|
onTouchStart(event) {
|
||||||
const changedTouches = event.changedTouches;
|
const changedTouches = event.changedTouches;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
// Clear the hold mode time out if another touch begins
|
// Clear the hold mode time out if another touch begins
|
||||||
if (this.holdModeTimeout)
|
if (this.holdModeTimeout)
|
||||||
|
@ -234,13 +271,14 @@
|
||||||
identifier: touch.identifier,
|
identifier: touch.identifier,
|
||||||
clientX: touch.clientX,
|
clientX: touch.clientX,
|
||||||
clientY: touch.clientY,
|
clientY: touch.clientY,
|
||||||
hasMoved: false
|
hasMoved: false,
|
||||||
|
gestured: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const connection = new Connection(`ws://${location.host}/gateway`, true);
|
const connection = new Connection(`ws://${location.host}/gateway`);
|
||||||
const controller = new TouchpadController(connection);
|
const controller = new TouchpadController(connection);
|
||||||
function main() {
|
function main() {
|
||||||
connection.connect();
|
connection.connect();
|
||||||
|
@ -249,10 +287,35 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
:root {
|
||||||
|
--body-bg-color: #2e2e2e;
|
||||||
|
--accent-bg-color: #d4d3d3;
|
||||||
|
--accent-color: #949494;
|
||||||
|
--grayed-text-color: #949494;
|
||||||
|
--button-accent-color: #3d3d3d;
|
||||||
|
--selected-bg-color: #2e2e2e;
|
||||||
|
--hover-bg-color: #4d4d4d;
|
||||||
|
--card-border-radius: 1rem;
|
||||||
|
--button-border-radius: 0.5rem;
|
||||||
|
--main-font-weight: 500;
|
||||||
|
|
||||||
|
--fonts-regular: "Noto Sans", "Liberation Sans", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-weight: var(--main-font-weight);
|
||||||
|
font-family: var(--fonts-regular);
|
||||||
|
background-color: var(--body-bg-color);
|
||||||
|
color: var(--accent-bg-color);
|
||||||
|
margin: 0;
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
.touchpad {
|
.touchpad {
|
||||||
width: 75vw;
|
height: 30rem;
|
||||||
height: 50vh;
|
width: 100%;
|
||||||
background-color: blue;
|
background-color: var(--accent-bg-color);
|
||||||
|
border-radius: var(--card-border-radius);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
Loading…
Reference in a new issue