1
0
mirror of synced 2025-02-13 09:02:37 +01:00

web: Fix touch input

This commit is contained in:
WerWolv 2024-07-03 22:32:33 +02:00
parent cfbc6e085a
commit 1d99f8534d
2 changed files with 96 additions and 2 deletions

View File

@ -100,7 +100,77 @@ var notWorkingTimer = setTimeout(() => {
var Module = { var Module = {
preRun: [], preRun: [],
postRun: [], postRun: function() {
// Patch the emscripten GLFW module to send mouse and touch events in the right order
// For ImGui interactions to correctly work with touch input, MousePos events need
// to be processed first and then MouseButton events in the next frame. By default,
// GLFW does the exact opposite, which causes buttons to require two taps to register
// and windows get "stuck" to the cursor when dragged or resized
GLFW.onMousemove = event => {
if (event.type === "touchmove") {
event.preventDefault();
let primaryChanged = false;
for (let i of event.changedTouches) {
if (GLFW.primaryTouchId === i.identifier) {
Browser.setMouseCoords(i.pageX, i.pageY);
primaryChanged = true;
break;
}
}
if (!primaryChanged) {
return;
}
} else {
Browser.calculateMouseEvent(event);
}
};
GLFW.onMouseButtonChanged = (event, status) => {
if (!GLFW.active) return;
if (event.target != Module["canvas"]) return;
const isTouchType = event.type === "touchstart" || event.type === "touchend" || event.type === "touchcancel";
let eventButton = 0;
if (isTouchType) {
event.preventDefault();
let primaryChanged = false;
if (GLFW.primaryTouchId === null && event.type === "touchstart" && event.targetTouches.length > 0) {
const chosenTouch = event.targetTouches[0];
GLFW.primaryTouchId = chosenTouch.identifier;
Browser.setMouseCoords(chosenTouch.pageX, chosenTouch.pageY);
primaryChanged = true;
} else if (event.type === "touchend" || event.type === "touchcancel") {
for (let i of event.changedTouches) {
if (GLFW.primaryTouchId === i.identifier) {
GLFW.primaryTouchId = null;
primaryChanged = true;
break;
}
}
}
if (!primaryChanged) {
return;
}
} else {
Browser.calculateMouseEvent(event);
eventButton = GLFW.DOMToGLFWMouseButton(event);
}
if (status == 1) {
GLFW.active.buttons |= (1 << eventButton);
try {
event.target.setCapture();
} catch (e) {}
} else {
GLFW.active.buttons &= ~(1 << eventButton);
}
if (GLFW.active.cursorPosFunc) {
getWasmTableEntry(GLFW.active.cursorPosFunc)(GLFW.active.id, Browser.mouseX, Browser.mouseY);
}
if (GLFW.active.mouseButtonFunc) {
getWasmTableEntry(GLFW.active.mouseButtonFunc)(GLFW.active.id, eventButton, status, GLFW.getModBits(GLFW.active));
}
};
},
onRuntimeInitialized: function() { onRuntimeInitialized: function() {
// Triggered when the wasm module is loaded and ready to use. // Triggered when the wasm module is loaded and ready to use.
document.getElementById("loading").style.display = "none" document.getElementById("loading").style.display = "none"
@ -157,7 +227,6 @@ window.addEventListener('resize', js_resizeCanvas, false);
function js_resizeCanvas() { function js_resizeCanvas() {
let canvas = document.getElementById('canvas'); let canvas = document.getElementById('canvas');
canvas.top = document.documentElement.clientTop; canvas.top = document.documentElement.clientTop;
canvas.left = document.documentElement.clientLeft; canvas.left = document.documentElement.clientLeft;
canvas.width = Math.min(document.documentElement.clientWidth, window.innerWidth || 0); canvas.width = Math.min(document.documentElement.clientWidth, window.innerWidth || 0);

View File

@ -7,6 +7,9 @@
#include <hex/api/event_manager.hpp> #include <hex/api/event_manager.hpp>
#include <imgui.h>
#include <imgui_internal.h>
// Function used by c++ to get the size of the html canvas // Function used by c++ to get the size of the html canvas
EM_JS(int, canvas_get_width, (), { EM_JS(int, canvas_get_width, (), {
return Module.canvas.width; return Module.canvas.width;
@ -37,6 +40,27 @@ extern "C" void handleThemeChange() {
hex::EventOSThemeChanged::post(); hex::EventOSThemeChanged::post();
} }
EM_JS(void, setupInputModeListener, (), {
Module.canvas.addEventListener('mousedown', function() {
Module._enterMouseMode();
});
Module.canvas.addEventListener('touchstart', function() {
Module._enterTouchMode();
});
});
EMSCRIPTEN_KEEPALIVE
extern "C" void enterMouseMode() {
ImGui::GetIO().AddMouseSourceEvent(ImGuiMouseSource_Mouse);
}
EMSCRIPTEN_KEEPALIVE
extern "C" void enterTouchMode() {
ImGui::GetIO().AddMouseSourceEvent(ImGuiMouseSource_TouchScreen);
}
namespace hex { namespace hex {
void nativeErrorMessage(const std::string &message) { void nativeErrorMessage(const std::string &message) {
@ -70,6 +94,7 @@ namespace hex {
void Window::setupNativeWindow() { void Window::setupNativeWindow() {
resizeCanvas(); resizeCanvas();
setupThemeListener(); setupThemeListener();
setupInputModeListener();
bool themeFollowSystem = ImHexApi::System::usesSystemThemeDetection(); bool themeFollowSystem = ImHexApi::System::usesSystemThemeDetection();
EventOSThemeChanged::subscribe(this, [themeFollowSystem] { EventOSThemeChanged::subscribe(this, [themeFollowSystem] {