"use strict"; /** * @constructor * * @param {BusConnector} bus */ function MouseAdapter(bus, screen_container) { /** @const */ var SPEED_FACTOR = 0.15; var left_down = false, right_down = false, middle_down = false, last_x = 0, last_y = 0, mouse = this; // set by controller this.enabled = false; // set by emulator this.emu_enabled = true; this.bus = bus; this.bus.register("mouse-enable", function(enabled) { this.enabled = enabled; }, this); // TODO: Should probably not use bus for this this.is_running = false; this.bus.register("emulator-stopped", function() { this.is_running = false; }, this); this.bus.register("emulator-started", function() { this.is_running = true; }, this); this.destroy = function() { if(typeof window === "undefined") { return; } window.removeEventListener("touchstart", touch_start_handler, false); window.removeEventListener("touchend", touch_end_handler, false); window.removeEventListener("touchmove", mousemove_handler, false); window.removeEventListener("mousemove", mousemove_handler, false); window.removeEventListener("mousedown", mousedown_handler, false); window.removeEventListener("mouseup", mouseup_handler, false); window.removeEventListener("wheel", mousewheel_handler, { passive: false }); }; this.init = function() { if(typeof window === "undefined") { return; } this.destroy(); window.addEventListener("touchstart", touch_start_handler, false); window.addEventListener("touchend", touch_end_handler, false); window.addEventListener("touchmove", mousemove_handler, false); window.addEventListener("mousemove", mousemove_handler, false); window.addEventListener("mousedown", mousedown_handler, false); window.addEventListener("mouseup", mouseup_handler, false); window.addEventListener("wheel", mousewheel_handler, { passive: false }); }; this.init(); function is_child(child, parent) { while(child.parentNode) { if(child === parent) { return true; } child = child.parentNode; } return false; } function may_handle(e) { if(!mouse.enabled || !mouse.emu_enabled) { return false; } const MOVE_MOUSE_WHEN_OVER_SCREEN_ONLY = true; if(MOVE_MOUSE_WHEN_OVER_SCREEN_ONLY) { var parent = screen_container || document.body; return document.pointerLockElement || is_child(e.target, parent); } else { if(e.type === "mousemove" || e.type === "touchmove") { return true; } if(e.type === "mousewheel" || e.type === "DOMMouseScroll") { return is_child(e.target, parent); } return !e.target || e.target.nodeName !== "INPUT" && e.target.nodeName !== "TEXTAREA"; } } function touch_start_handler(e) { if(may_handle(e)) { var touches = e["changedTouches"]; if(touches && touches.length) { var touch = touches[touches.length - 1]; last_x = touch.clientX; last_y = touch.clientY; } } } function touch_end_handler(e) { if(left_down || middle_down || right_down) { mouse.bus.send("mouse-click", [false, false, false]); left_down = middle_down = right_down = false; } } function mousemove_handler(e) { if(!mouse.bus) { return; } if(!may_handle(e)) { return; } if(!mouse.is_running) { return; } var delta_x = 0; var delta_y = 0; var touches = e["changedTouches"]; if(touches) { if(touches.length) { var touch = touches[touches.length - 1]; delta_x = touch.clientX - last_x; delta_y = touch.clientY - last_y; last_x = touch.clientX; last_y = touch.clientY; e.preventDefault(); } } else { if(typeof e["movementX"] === "number") { delta_x = e["movementX"]; delta_y = e["movementY"]; } else if(typeof e["webkitMovementX"] === "number") { delta_x = e["webkitMovementX"]; delta_y = e["webkitMovementY"]; } else if(typeof e["mozMovementX"] === "number") { delta_x = e["mozMovementX"]; delta_y = e["mozMovementY"]; } else { // Fallback for other browsers? delta_x = e.clientX - last_x; delta_y = e.clientY - last_y; last_x = e.clientX; last_y = e.clientY; } } delta_x *= SPEED_FACTOR; delta_y *= SPEED_FACTOR; //if(Math.abs(delta_x) > 100 || Math.abs(delta_y) > 100) //{ // // Large mouse delta, drop? //} delta_y = -delta_y; mouse.bus.send("mouse-delta", [delta_x, delta_y]); if(screen_container) { let absolute_x = e.pageX - screen_container.offsetLeft; let absolute_y = e.pageY - screen_container.offsetTop; mouse.bus.send("mouse-absolute", [ absolute_x, absolute_y, screen_container.offsetWidth, screen_container.offsetHeight]); } } function mousedown_handler(e) { if(may_handle(e)) { click_event(e, true); } } function mouseup_handler(e) { if(may_handle(e)) { click_event(e, false); } } function click_event(e, down) { if(!mouse.bus) { return; } if(e.which === 1) { left_down = down; } else if(e.which === 2) { middle_down = down; } else if(e.which === 3) { right_down = down; } else { dbg_log("Unknown event.which: " + e.which); } mouse.bus.send("mouse-click", [left_down, middle_down, right_down]); e.preventDefault(); } function mousewheel_handler(e) { if(!may_handle(e)) { return; } var delta_x = e.wheelDelta || -e.detail; var delta_y = 0; if(delta_x < 0) { delta_x = -1; } else if(delta_x > 0) { delta_x = 1; } mouse.bus.send("mouse-wheel", [delta_x, delta_y]); e.preventDefault(); } }