diff options
| -rw-r--r-- | src/core/hid/emulated_console.cpp | 15 | ||||
| -rw-r--r-- | src/core/hid/input_converter.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/touchscreen.cpp | 6 | ||||
| -rw-r--r-- | src/input_common/drivers/touch_screen.cpp | 89 | ||||
| -rw-r--r-- | src/input_common/drivers/touch_screen.h | 52 | ||||
| -rw-r--r-- | src/yuzu/bootmanager.cpp | 58 | ||||
| -rw-r--r-- | src/yuzu/bootmanager.h | 6 | ||||
| -rw-r--r-- | src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | 2 | 
8 files changed, 140 insertions, 92 deletions
| diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index fd220ccb5..aac45907d 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp @@ -27,12 +27,19 @@ void EmulatedConsole::SetTouchParams() {          // We can't use mouse as touch if native mouse is enabled          touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"};      } -    touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:0,axis_y:1,button:0"}; -    touch_params[index++] = Common::ParamPackage{"engine:touch,axis_x:2,axis_y:3,button:1"}; + +    touch_params[index++] = +        Common::ParamPackage{"engine:touch,axis_x:0,axis_y:1,button:0,touch_id:0"}; +    touch_params[index++] = +        Common::ParamPackage{"engine:touch,axis_x:2,axis_y:3,button:1,touch_id:1"}; +    touch_params[index++] = +        Common::ParamPackage{"engine:touch,axis_x:4,axis_y:5,button:2,touch_id:2"}; +    touch_params[index++] = +        Common::ParamPackage{"engine:touch,axis_x:6,axis_y:7,button:3,touch_id:3"};      touch_params[index++] = -        Common::ParamPackage{"engine:cemuhookudp,axis_x:17,axis_y:18,button:65536"}; +        Common::ParamPackage{"engine:cemuhookudp,axis_x:17,axis_y:18,button:65536,touch_id:0"};      touch_params[index++] = -        Common::ParamPackage{"engine:cemuhookudp,axis_x:19,axis_y:20,button:131072"}; +        Common::ParamPackage{"engine:cemuhookudp,axis_x:19,axis_y:20,button:131072,touch_id:1"};      const auto button_index =          static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue()); diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp index 3c26260f3..18d9f042d 100644 --- a/src/core/hid/input_converter.cpp +++ b/src/core/hid/input_converter.cpp @@ -1,6 +1,7 @@  // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project  // SPDX-License-Identifier: GPL-2.0-or-later +#include <algorithm>  #include <random>  #include "common/input.h" @@ -196,6 +197,9 @@ Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus&      x = std::clamp(x, 0.0f, 1.0f);      y = std::clamp(y, 0.0f, 1.0f); +    // Limit id to maximum number of fingers +    status.id = std::clamp(status.id, 0, 16); +      if (status.pressed.inverted) {          status.pressed.value = !status.pressed.value;      } diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index 108ce5a41..1da8d3eb0 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp @@ -44,7 +44,6 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin      for (std::size_t id = 0; id < MAX_FINGERS; id++) {          const auto& current_touch = touch_status[id];          auto& finger = fingers[id]; -        finger.position = current_touch.position;          finger.id = current_touch.id;          if (finger.attribute.start_touch) { @@ -61,13 +60,18 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin          if (!finger.pressed && current_touch.pressed) {              finger.attribute.start_touch.Assign(1);              finger.pressed = true; +            finger.position = current_touch.position;              continue;          }          if (finger.pressed && !current_touch.pressed) {              finger.attribute.raw = 0;              finger.attribute.end_touch.Assign(1); +            continue;          } + +        // Only update position if touch is not on a special frame +        finger.position = current_touch.position;      }      std::array<Core::HID::TouchFinger, MAX_FINGERS> active_fingers; diff --git a/src/input_common/drivers/touch_screen.cpp b/src/input_common/drivers/touch_screen.cpp index 8acbe4584..1753e0893 100644 --- a/src/input_common/drivers/touch_screen.cpp +++ b/src/input_common/drivers/touch_screen.cpp @@ -14,38 +14,93 @@ constexpr PadIdentifier identifier = {  TouchScreen::TouchScreen(std::string input_engine_) : InputEngine(std::move(input_engine_)) {      PreSetController(identifier); +    ReleaseAllTouch();  } -void TouchScreen::TouchMoved(float x, float y, std::size_t finger) { -    if (finger >= 16) { +void TouchScreen::TouchMoved(float x, float y, std::size_t finger_id) { +    const auto index = GetIndexFromFingerId(finger_id); +    if (!index) { +        // Touch doesn't exist handle it as a new one +        TouchPressed(x, y, finger_id);          return;      } -    TouchPressed(x, y, finger); +    const auto i = index.value(); +    fingers[i].is_active = true; +    SetButton(identifier, static_cast<int>(i), true); +    SetAxis(identifier, static_cast<int>(i * 2), x); +    SetAxis(identifier, static_cast<int>(i * 2 + 1), y);  } -void TouchScreen::TouchPressed(float x, float y, std::size_t finger) { -    if (finger >= 16) { +void TouchScreen::TouchPressed(float x, float y, std::size_t finger_id) { +    if (GetIndexFromFingerId(finger_id)) { +        // Touch already exist. Just update the data +        TouchMoved(x, y, finger_id);          return;      } -    SetButton(identifier, static_cast<int>(finger), true); -    SetAxis(identifier, static_cast<int>(finger * 2), x); -    SetAxis(identifier, static_cast<int>(finger * 2 + 1), y); +    const auto index = GetNextFreeIndex(); +    if (!index) { +        // No free entries. Ignore input +        return; +    } +    const auto i = index.value(); +    fingers[i].is_enabled = true; +    fingers[i].finger_id = finger_id; +    TouchMoved(x, y, finger_id);  } -void TouchScreen::TouchReleased(std::size_t finger) { -    if (finger >= 16) { +void TouchScreen::TouchReleased(std::size_t finger_id) { +    const auto index = GetIndexFromFingerId(finger_id); +    if (!index) {          return;      } -    SetButton(identifier, static_cast<int>(finger), false); -    SetAxis(identifier, static_cast<int>(finger * 2), 0.0f); -    SetAxis(identifier, static_cast<int>(finger * 2 + 1), 0.0f); +    const auto i = index.value(); +    fingers[i].is_enabled = false; +    SetButton(identifier, static_cast<int>(i), false); +    SetAxis(identifier, static_cast<int>(i * 2), 0.0f); +    SetAxis(identifier, static_cast<int>(i * 2 + 1), 0.0f); +} + +std::optional<std::size_t> TouchScreen::GetIndexFromFingerId(std::size_t finger_id) const { +    for (std::size_t index = 0; index < MAX_FINGER_COUNT; ++index) { +        const auto& finger = fingers[index]; +        if (!finger.is_enabled) { +            continue; +        } +        if (finger.finger_id == finger_id) { +            return index; +        } +    } +    return std::nullopt; +} + +std::optional<std::size_t> TouchScreen::GetNextFreeIndex() const { +    for (std::size_t index = 0; index < MAX_FINGER_COUNT; ++index) { +        if (!fingers[index].is_enabled) { +            return index; +        } +    } +    return std::nullopt; +} + +void TouchScreen::ClearActiveFlag() { +    for (auto& finger : fingers) { +        finger.is_active = false; +    } +} + +void TouchScreen::ReleaseInactiveTouch() { +    for (const auto& finger : fingers) { +        if (!finger.is_active) { +            TouchReleased(finger.finger_id); +        } +    }  }  void TouchScreen::ReleaseAllTouch() { -    for (int index = 0; index < 16; ++index) { -        SetButton(identifier, index, false); -        SetAxis(identifier, index * 2, 0.0f); -        SetAxis(identifier, index * 2 + 1, 0.0f); +    for (const auto& finger : fingers) { +        if (finger.is_enabled) { +            TouchReleased(finger.finger_id); +        }      }  } diff --git a/src/input_common/drivers/touch_screen.h b/src/input_common/drivers/touch_screen.h index 193478ead..f46036ffd 100644 --- a/src/input_common/drivers/touch_screen.h +++ b/src/input_common/drivers/touch_screen.h @@ -3,41 +3,65 @@  #pragma once +#include <optional> +  #include "input_common/input_engine.h"  namespace InputCommon {  /** - * A button device factory representing a keyboard. It receives keyboard events and forward them - * to all button devices it created. + * A touch device factory representing a touch screen. It receives touch events and forward them + * to all touch devices it created.   */  class TouchScreen final : public InputEngine {  public:      explicit TouchScreen(std::string input_engine_);      /** -     * Signals that mouse has moved. -     * @param x the x-coordinate of the cursor -     * @param y the y-coordinate of the cursor -     * @param center_x the x-coordinate of the middle of the screen -     * @param center_y the y-coordinate of the middle of the screen +     * Signals that touch has moved and marks this touch point as active +     * @param x new horizontal position +     * @param y new vertical position +     * @param finger_id of the touch point to be updated       */ -    void TouchMoved(float x, float y, std::size_t finger); +    void TouchMoved(float x, float y, std::size_t finger_id);      /** -     * Sets the status of all buttons bound with the key to pressed -     * @param key_code the code of the key to press +     * Signals and creates a new touch point with this finger id +     * @param x starting horizontal position +     * @param y starting vertical position +     * @param finger_id to be assigned to the new touch point       */ -    void TouchPressed(float x, float y, std::size_t finger); +    void TouchPressed(float x, float y, std::size_t finger_id);      /** -     * Sets the status of all buttons bound with the key to released -     * @param key_code the code of the key to release +     * Signals and resets the touch point related to the this finger id +     * @param finger_id to be released       */ -    void TouchReleased(std::size_t finger); +    void TouchReleased(std::size_t finger_id); + +    /// Resets the active flag for each touch point +    void ClearActiveFlag(); + +    /// Releases all touch that haven't been marked as active +    void ReleaseInactiveTouch();      /// Resets all inputs to their initial value      void ReleaseAllTouch(); + +private: +    static constexpr std::size_t MAX_FINGER_COUNT = 16; + +    struct TouchStatus { +        std::size_t finger_id{}; +        bool is_enabled{}; +        bool is_active{}; +    }; + +    std::optional<std::size_t> GetIndexFromFingerId(std::size_t finger_id) const; + +    std::optional<std::size_t> GetNextFreeIndex() const; + +    std::array<TouchStatus, MAX_FINGER_COUNT> fingers{};  };  } // namespace InputCommon diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index a1b819ae0..8f0a6bbb8 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -772,65 +772,25 @@ void GRenderWindow::wheelEvent(QWheelEvent* event) {  void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) {      QList<QTouchEvent::TouchPoint> touch_points = event->touchPoints();      for (const auto& touch_point : touch_points) { -        if (!TouchUpdate(touch_point)) { -            TouchStart(touch_point); -        } +        const auto [x, y] = ScaleTouch(touch_point.pos()); +        const auto [touch_x, touch_y] = MapToTouchScreen(x, y); +        input_subsystem->GetTouchScreen()->TouchPressed(touch_x, touch_y, touch_point.id());      }  }  void GRenderWindow::TouchUpdateEvent(const QTouchEvent* event) {      QList<QTouchEvent::TouchPoint> touch_points = event->touchPoints(); +    input_subsystem->GetTouchScreen()->ClearActiveFlag();      for (const auto& touch_point : touch_points) { -        if (!TouchUpdate(touch_point)) { -            TouchStart(touch_point); -        } -    } -    // Release all inactive points -    for (std::size_t id = 0; id < touch_ids.size(); ++id) { -        if (!TouchExist(touch_ids[id], touch_points)) { -            touch_ids[id] = 0; -            input_subsystem->GetTouchScreen()->TouchReleased(id); -        } +        const auto [x, y] = ScaleTouch(touch_point.pos()); +        const auto [touch_x, touch_y] = MapToTouchScreen(x, y); +        input_subsystem->GetTouchScreen()->TouchMoved(touch_x, touch_y, touch_point.id());      } +    input_subsystem->GetTouchScreen()->ReleaseInactiveTouch();  }  void GRenderWindow::TouchEndEvent() { -    for (std::size_t id = 0; id < touch_ids.size(); ++id) { -        if (touch_ids[id] != 0) { -            touch_ids[id] = 0; -            input_subsystem->GetTouchScreen()->TouchReleased(id); -        } -    } -} - -void GRenderWindow::TouchStart(const QTouchEvent::TouchPoint& touch_point) { -    for (std::size_t id = 0; id < touch_ids.size(); ++id) { -        if (touch_ids[id] == 0) { -            touch_ids[id] = touch_point.id() + 1; -            const auto [x, y] = ScaleTouch(touch_point.pos()); -            const auto [touch_x, touch_y] = MapToTouchScreen(x, y); -            input_subsystem->GetTouchScreen()->TouchPressed(touch_x, touch_y, id); -        } -    } -} - -bool GRenderWindow::TouchUpdate(const QTouchEvent::TouchPoint& touch_point) { -    for (std::size_t id = 0; id < touch_ids.size(); ++id) { -        if (touch_ids[id] == static_cast<std::size_t>(touch_point.id() + 1)) { -            const auto [x, y] = ScaleTouch(touch_point.pos()); -            const auto [touch_x, touch_y] = MapToTouchScreen(x, y); -            input_subsystem->GetTouchScreen()->TouchMoved(touch_x, touch_y, id); -            return true; -        } -    } -    return false; -} - -bool GRenderWindow::TouchExist(std::size_t id, -                               const QList<QTouchEvent::TouchPoint>& touch_points) const { -    return std::any_of(touch_points.begin(), touch_points.end(), [id](const auto& point) { -        return id == static_cast<std::size_t>(point.id() + 1); -    }); +    input_subsystem->GetTouchScreen()->ReleaseAllTouch();  }  bool GRenderWindow::event(QEvent* event) { diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index 4b0ce0293..841816564 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -217,10 +217,6 @@ private:      void TouchUpdateEvent(const QTouchEvent* event);      void TouchEndEvent(); -    void TouchStart(const QTouchEvent::TouchPoint& touch_point); -    bool TouchUpdate(const QTouchEvent::TouchPoint& touch_point); -    bool TouchExist(std::size_t id, const QList<QTouchEvent::TouchPoint>& touch_points) const; -      void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override;      bool InitializeOpenGL(); @@ -246,8 +242,6 @@ private:      bool first_frame = false;      InputCommon::TasInput::TasState last_tas_state; -    std::array<std::size_t, 16> touch_ids{}; -      Core::System& system;  protected: diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index ae2e62dc5..71c413e64 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp @@ -93,7 +93,7 @@ void EmuWindow_SDL2::OnFingerMotion(float x, float y, std::size_t id) {  }  void EmuWindow_SDL2::OnFingerUp() { -    input_subsystem->GetTouchScreen()->TouchReleased(0); +    input_subsystem->GetTouchScreen()->ReleaseAllTouch();  }  void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) { | 
