#include "InputHandler.h" void InputHandler::routePointerEvent(PointerEvent event) { // Lookup existing streams auto it = streams.find(event.pointerId); if (it != streams.end()) { it->second->AddInput(event); if (it->second->GetComplete()) { streams.erase(it); } } else { // Stream does not exist if (event.actDirection == PointerDirection::Down) { streams[event.pointerId] = std::make_shared(event); // Call registered callbacks for (std::weak_ptr callback : onDownCallbacks) { std::shared_ptr callbackPtr = callback.lock(); if (callbackPtr) { if (callbackPtr->OnDown(streams[event.pointerId])) { break; // layer has consumed the stream } } } } } } void InputHandler::routeScrollEvent(SDL_MouseWheelEvent e) { for (std::weak_ptr callback : onDownCallbacks) { std::shared_ptr callbackPtr = callback.lock(); if (callbackPtr) { if (callbackPtr->OnScroll(e)) { break; // layer has consumed the stream } } } } // Push SDL_MouseMotionEvent to the pointer queue void InputHandler::onMouseMotionEvent(SDL_MouseMotionEvent e) { PointerEvent event; event.pointerId = e.which; event.timestampNanos = e.timestamp; event.action = 0; event.actDirection = PointerDirection::None; event.screenX = e.x; event.screenY = e.y; CursorX = e.x; CursorY = e.y; event.pressure = 1.0f; routePointerEvent(event); } // Push SDL_MouseButtonEvent to the pointer queue void InputHandler::onMouseButtonEvent(SDL_MouseButtonEvent e) { // Create PointerEvent PointerEvent event; event.pointerId = e.which; event.timestampNanos = e.timestamp; switch (e.button) { default: case SDL_BUTTON_LEFT: // TODO: Test if SDL implements left-handed mode event.action = (int)PointerAction::GenericPrimary; break; case SDL_BUTTON_RIGHT: event.action = (int)PointerAction::SecondaryMouseButton; break; case SDL_BUTTON_MIDDLE: event.action = (int)PointerAction::TertiaryMouseButton; break; case SDL_BUTTON_X1: event.action = (int)PointerAction::MousePrimarySide; break; case SDL_BUTTON_X2: event.action = (int)PointerAction::MouseSecondarySide; break; } event.actDirection = e.down ? PointerDirection::Down : PointerDirection::Up; event.screenX = e.x; event.screenY = e.y; CursorX = e.x; CursorY = e.y; event.pressure = 1.0f; routePointerEvent(event); } void InputHandler::onPenTouchEvent(SDL_PenTouchEvent e) { // Create PointerEvent PointerEvent event; event.pointerId = e.which; event.timestampNanos = e.timestamp; event.action = (int)PointerAction::GenericPrimary; event.actDirection = e.down ? PointerDirection::Down : PointerDirection::Up; event.screenX = e.x; event.screenY = e.y; CursorX = e.x; CursorY = e.y; event.pressure = 0.0f; routePointerEvent(event); } void InputHandler::onScroll(SDL_Event e) { routeScrollEvent(e.wheel); } void InputHandler::onPenMotionEvent(SDL_PenMotionEvent e) { PointerEvent event; event.pointerId = e.which; event.timestampNanos = e.timestamp; event.action = 0; event.actDirection = PointerDirection::None; event.screenX = e.x; event.screenY = e.y; CursorX = e.x; CursorY = e.y; event.pressure = pressure.find(e.which) == pressure.end() ? 0.0f : pressure[e.which]; routePointerEvent(event); } void InputHandler::onPenAxisEvent(SDL_PenAxisEvent e) { if (e.axis != SDL_PEN_AXIS_PRESSURE) { return; } if (pressure.find(e.which) == pressure.end()) { pressure.insert({ e.which, e.value }); } else { pressure[e.which] = e.value; } } void InputHandler::onStylus(SDL_Event e) { switch (e.type) { case SDL_EVENT_PEN_AXIS: onPenAxisEvent(e.paxis); break; case SDL_EVENT_PEN_DOWN: case SDL_EVENT_PEN_UP: onPenTouchEvent(e.ptouch); break; case SDL_EVENT_PEN_MOTION: onPenMotionEvent(e.pmotion); break; default: break; } } void InputHandler::onKeyboard(SDL_Event e) { switch (e.type) { case SDL_EVENT_KEY_DOWN: KeysHeld.push_back(e.key.key); KeysDown.push_back(e.key.key); break; case SDL_EVENT_KEY_UP: KeysHeld.remove(e.key.key); if (IsKeyDown(e.key.key)) { KeysDown.remove(e.key.key); } break; default: break; } } std::list InputHandler::KeysHeld; std::list InputHandler::KeysDown; bool InputHandler::IsKeyHeld(SDL_Keycode key) { for (SDL_Keycode heldKey : KeysHeld) { if (heldKey == key) { return true; } } return false; } bool InputHandler::IsKeyDown(SDL_Keycode key) { for (SDL_Keycode heldKey : KeysDown) { if (heldKey == key) { KeysDown.remove(heldKey); return true; } } return false; } void InputHandler::onMouse(SDL_Event e) { switch (e.type) { case SDL_EVENT_MOUSE_BUTTON_DOWN: case SDL_EVENT_MOUSE_BUTTON_UP: onMouseButtonEvent(e.button); break; case SDL_EVENT_MOUSE_MOTION: onMouseMotionEvent(e.motion); break; default: break; } } bool InputHandler::OnSDLEvent(SDL_Event e) { bool handled = false; switch (e.type) { case SDL_EVENT_MOUSE_BUTTON_DOWN: case SDL_EVENT_MOUSE_BUTTON_UP: case SDL_EVENT_MOUSE_MOTION: onMouse(e); handled = true; break; case SDL_EVENT_PEN_AXIS: case SDL_EVENT_PEN_DOWN: case SDL_EVENT_PEN_UP: case SDL_EVENT_PEN_MOTION: onStylus(e); handled = true; break; case SDL_EVENT_KEY_DOWN: case SDL_EVENT_KEY_UP: onKeyboard(e); handled = true; break; case SDL_EVENT_MOUSE_WHEEL: onScroll(e); handled = true; break; default: break; } return handled; } double InputHandler::CursorX = 0.0; double InputHandler::CursorY = 0.0;