Skip to content

Commit

Permalink
feat: basic Mouse implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
ABeltramo committed Feb 18, 2024
1 parent 8414cd5 commit 5682af0
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 5 deletions.
67 changes: 63 additions & 4 deletions src/server/server/rest.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,25 @@ handle_device(inputtino::Result<std::shared_ptr<T>> &result, httplib::Response &
}
}

/**
* Turns a string into a MOUSE_BUTTON
*/
static inputtino::Mouse::MOUSE_BUTTON
to_mouse_button(const std::string &button) {
switch (hash(to_lower(button))) {
case hash("left"):
return inputtino::Mouse::MOUSE_BUTTON::LEFT;
case hash("right"):
return inputtino::Mouse::MOUSE_BUTTON::RIGHT;
case hash("middle"):
return inputtino::Mouse::MOUSE_BUTTON::MIDDLE;
case hash("side"):
return inputtino::Mouse::MOUSE_BUTTON::SIDE;
case hash("extra"):
return inputtino::Mouse::MOUSE_BUTTON::EXTRA;
}
}

std::unique_ptr<httplib::Server> setup_rest_server(std::shared_ptr<immer::atom<ServerState>> state) {
auto svr = std::make_unique<httplib::Server>();

Expand Down Expand Up @@ -126,15 +145,55 @@ std::unique_ptr<httplib::Server> setup_rest_server(std::shared_ptr<immer::atom<S
svr->Post("/api/v1.0/devices/mouse/:id/move_rel", [state](const httplib::Request &req, httplib::Response &res) {
std::size_t id = std::stoul(req.path_params.at("id"));
auto payload = json::parse(req.body);
double delta_x = payload.value("delta_x", 0.0);
double delta_y = payload.value("delta_y", 0.0);
auto device = state->load()->devices.at(id);
auto mouse = std::get<std::shared_ptr<inputtino::Mouse>>(device->device);
mouse->move(delta_x, delta_y);
mouse->move(payload.value("delta_x", 0.0), payload.value("delta_y", 0.0));
res.set_content(json{{"success", true}}.dump(), "application/json");
});

svr->Post("/api/v1.0/devices/mouse/:id/move_abs", [state](const httplib::Request &req, httplib::Response &res) {
std::size_t id = std::stoul(req.path_params.at("id"));
auto payload = json::parse(req.body);
auto device = state->load()->devices.at(id);
auto mouse = std::get<std::shared_ptr<inputtino::Mouse>>(device->device);
mouse->move_abs(payload.value("abs_x", 0.0), payload.value("abs_y", 0.0), payload.value("screen_width", 0.0),
payload.value("screen_height", 0.0));
res.set_content(json{{"success", true}}.dump(), "application/json");
});

// TODO: implement all other handlers...
svr->Post("/api/v1.0/devices/mouse/:id/press", [state](const httplib::Request &req, httplib::Response &res) {
std::size_t id = std::stoul(req.path_params.at("id"));
auto payload = json::parse(req.body);
auto device = state->load()->devices.at(id);
auto mouse = std::get<std::shared_ptr<inputtino::Mouse>>(device->device);
mouse->press(to_mouse_button(payload.value("button", "LEFT")));
res.set_content(json{{"success", true}}.dump(), "application/json");
});

svr->Post("/api/v1.0/devices/mouse/:id/release", [state](const httplib::Request &req, httplib::Response &res) {
std::size_t id = std::stoul(req.path_params.at("id"));
auto payload = json::parse(req.body);
auto device = state->load()->devices.at(id);
auto mouse = std::get<std::shared_ptr<inputtino::Mouse>>(device->device);
mouse->release(to_mouse_button(payload.value("button", "LEFT")));
res.set_content(json{{"success", true}}.dump(), "application/json");
});

svr->Post("/api/v1.0/devices/mouse/:id/scroll", [state](const httplib::Request &req, httplib::Response &res) {
std::size_t id = std::stoul(req.path_params.at("id"));
auto payload = json::parse(req.body);
auto device = state->load()->devices.at(id);
auto mouse = std::get<std::shared_ptr<inputtino::Mouse>>(device->device);
switch (hash(to_lower(payload.value("direction", "vertical")))) {
case hash("vertical"):
mouse->vertical_scroll(payload.value("distance", 0.0));
break;
case hash("horizontal"):
mouse->horizontal_scroll(payload.value("distance", 0.0));
break;
}
res.set_content(json{{"success", true}}.dump(), "application/json");
});

/* Default error handling */
svr->set_exception_handler([](const auto &req, auto &res, std::exception_ptr ep) {
Expand Down
8 changes: 7 additions & 1 deletion src/server/web-client/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import AddDevice from "./lib/AddDevice.svelte";
import RemoveDevice from "./lib/RemoveDevice.svelte";
import FetchRequest from "./lib/FetchRequest.svelte";
import {selected_device} from "./lib/stores";
import Mouse from "./lib/Mouse.svelte";
import {Toolbar, ToolbarGroup, DarkMode, Toast} from 'flowbite-svelte';
import {FireOutline} from "flowbite-svelte-icons";
</script>
Expand All @@ -18,7 +20,11 @@
<DarkMode slot="end"/>
</Toolbar>

<FetchRequest />
{#if $selected_device?.type === "MOUSE"}
<Mouse/>
{/if}

<FetchRequest/>
</main>

<style>
Expand Down
52 changes: 52 additions & 0 deletions src/server/web-client/src/lib/Mouse.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<script lang="ts">
import {request, selected_device} from "./stores";
import {onDestroy} from "svelte";
let canvas: HTMLCanvasElement;
async function lock_mouse() {
await canvas.requestPointerLock({
unadjustedMovement: true,
});
}
document.addEventListener("pointerlockchange", lockChangeAlert, false);
function lockChangeAlert() {
if (document.pointerLockElement === canvas) {
console.log("The pointer lock status is now locked");
document.addEventListener("mousemove", updatePosition, false);
} else {
console.log("The pointer lock status is now unlocked");
document.removeEventListener("mousemove", updatePosition, false);
}
}
onDestroy(() => {
document.removeEventListener("mousemove", updatePosition, false);
});
function updatePosition(e: MouseEvent) {
if ($selected_device?.type === "MOUSE") {
request("/devices/mouse/" + $selected_device?.device_id + "/move_rel", "POST", {
"delta_x": e.movementX,
"delta_y": e.movementY
});
}
}
</script>

<p class="text-center dark:text-white">Click to lock the mouse</p>

<canvas width="640" height="360" bind:this={canvas} on:click={lock_mouse}>
<p>Your browser does not support the canvas element.</p>
</canvas>

<style>
canvas {
display: block;
margin: 0 auto;
border: 1px solid black;
}
</style>

0 comments on commit 5682af0

Please sign in to comment.