From 543232436fae8d1d0f9fdd94baf0ca88d4eea067 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 8 Mar 2015 03:13:26 -0400 Subject: EmuWindow: Added infrastructure code to enable touchpad support. --- src/common/emu_window.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++++++- src/common/emu_window.h | 29 +++++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) (limited to 'src/common') diff --git a/src/common/emu_window.cpp b/src/common/emu_window.cpp index 6459d2f32..11e6ad76b 100644 --- a/src/common/emu_window.cpp +++ b/src/common/emu_window.cpp @@ -5,6 +5,8 @@ #include "emu_window.h" #include "video_core/video_core.h" +bool EmuWindow::touch_pressed = false; + void EmuWindow::KeyPressed(KeyMap::HostDeviceKey key) { Service::HID::PadState mapped_key = KeyMap::GetPadKey(key); @@ -17,7 +19,68 @@ void EmuWindow::KeyReleased(KeyMap::HostDeviceKey key) { Service::HID::PadButtonRelease(mapped_key); } -EmuWindow::FramebufferLayout EmuWindow::FramebufferLayout::DefaultScreenLayout(unsigned width, unsigned height) { +/** + * Check if the given x/y coordinates are within the touchpad specified by the framebuffer layout + * @param layout FramebufferLayout object describing the framebuffer size and screen positions + * @param framebuffer_x Framebuffer x-coordinate to check + * @param framebuffer_y Framebuffer y-coordinate to check + * @return True if the coordinates are within the touchpad, otherwise false + */ +static bool IsWithinTouchscreen(const EmuWindow::FramebufferLayout& layout, unsigned framebuffer_x, + unsigned framebuffer_y) { + + return (framebuffer_y >= layout.bottom_screen.top && + framebuffer_y < layout.bottom_screen.bottom && + framebuffer_x >= layout.bottom_screen.left && + framebuffer_x < layout.bottom_screen.right); +} + +void EmuWindow::TouchPressed(const FramebufferLayout& layout, unsigned framebuffer_x, + unsigned framebuffer_y) { + + if (IsWithinTouchscreen(layout, framebuffer_x, framebuffer_y)) { + u16 touch_x = VideoCore::kScreenBottomWidth * (framebuffer_x - layout.bottom_screen.left) / + (layout.bottom_screen.right - layout.bottom_screen.left); + u16 touch_y = VideoCore::kScreenBottomHeight * (framebuffer_y - layout.bottom_screen.top) / + (layout.bottom_screen.bottom - layout.bottom_screen.top); + + Service::HID::TouchPress(touch_x, touch_y); + Service::HID::TouchUpdateComplete(); + + touch_pressed = true; + } +} + +void EmuWindow::TouchReleased(const FramebufferLayout& layout, unsigned framebuffer_x, + unsigned framebuffer_y) { + + if (IsWithinTouchscreen(layout, framebuffer_x, framebuffer_y)) { + + Service::HID::TouchRelease(); + Service::HID::TouchUpdateComplete(); + + touch_pressed = false; + } +} + +void EmuWindow::TouchMoved(const FramebufferLayout& layout, unsigned framebuffer_x, + unsigned framebuffer_y) { + + if (touch_pressed) { + if (IsWithinTouchscreen(layout, framebuffer_x, framebuffer_y)) { + EmuWindow::TouchPressed(layout, framebuffer_x, framebuffer_y); + } else { + Service::HID::TouchRelease(); + Service::HID::TouchUpdateComplete(); + + touch_pressed = false; + } + } +} + +EmuWindow::FramebufferLayout EmuWindow::FramebufferLayout::DefaultScreenLayout(unsigned width, + unsigned height) { + ASSERT(width > 0); ASSERT(height > 0); diff --git a/src/common/emu_window.h b/src/common/emu_window.h index f6099fdb6..df81e9e0f 100644 --- a/src/common/emu_window.h +++ b/src/common/emu_window.h @@ -76,6 +76,33 @@ public: /// Signals a key release action to the HID module static void KeyReleased(KeyMap::HostDeviceKey key); + /** + * Signal that a touch pressed event has occurred (e.g. mouse click pressed) + * @param layout FramebufferLayout object describing the framebuffer size and screen positions + * @param framebuffer_x Framebuffer x-coordinate that was pressed + * @param framebuffer_y Framebuffer y-coordinate that was pressed + */ + static void TouchPressed(const FramebufferLayout& layout, unsigned framebuffer_x, + unsigned framebuffer_y); + + /** + * Signal that a touch released event has occurred (e.g. mouse click released) + * @param layout FramebufferLayout object describing the framebuffer size and screen positions + * @param framebuffer_x Framebuffer x-coordinate that was released + * @param framebuffer_y Framebuffer y-coordinate that was released + */ + static void TouchReleased(const FramebufferLayout& layout, unsigned framebuffer_x, + unsigned framebuffer_y); + + /** + * Signal that a touch movement event has occurred (e.g. mouse was moved over the emu window) + * @param layout FramebufferLayout object describing the framebuffer size and screen positions + * @param framebuffer_x Framebuffer x-coordinate + * @param framebuffer_y Framebuffer y-coordinate + */ + static void TouchMoved(const FramebufferLayout& layout, unsigned framebuffer_x, + unsigned framebuffer_y); + /** * Returns currently active configuration. * @note Accesses to the returned object need not be consistent because it may be modified in another thread @@ -168,4 +195,6 @@ private: WindowConfig config; ///< Internal configuration (changes pending for being applied in ProcessConfigurationChanges) WindowConfig active_config; ///< Internal active configuration + + static bool touch_pressed; ///< True if touchpad area is currently pressed, otherwise false }; -- cgit v1.2.3 From 953e09ddb5cab8f4d8606966020e8eefa20e04ce Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 8 Mar 2015 21:45:45 -0400 Subject: EmuWindow: Made pad/touch functions non-static. --- src/common/emu_window.cpp | 2 -- src/common/emu_window.h | 15 ++++++--------- 2 files changed, 6 insertions(+), 11 deletions(-) (limited to 'src/common') diff --git a/src/common/emu_window.cpp b/src/common/emu_window.cpp index 11e6ad76b..89bb89481 100644 --- a/src/common/emu_window.cpp +++ b/src/common/emu_window.cpp @@ -5,8 +5,6 @@ #include "emu_window.h" #include "video_core/video_core.h" -bool EmuWindow::touch_pressed = false; - void EmuWindow::KeyPressed(KeyMap::HostDeviceKey key) { Service::HID::PadState mapped_key = KeyMap::GetPadKey(key); diff --git a/src/common/emu_window.h b/src/common/emu_window.h index df81e9e0f..8e4b510e9 100644 --- a/src/common/emu_window.h +++ b/src/common/emu_window.h @@ -71,10 +71,10 @@ public: virtual void ReloadSetKeymaps() = 0; /// Signals a key press action to the HID module - static void KeyPressed(KeyMap::HostDeviceKey key); + void KeyPressed(KeyMap::HostDeviceKey key); /// Signals a key release action to the HID module - static void KeyReleased(KeyMap::HostDeviceKey key); + void KeyReleased(KeyMap::HostDeviceKey key); /** * Signal that a touch pressed event has occurred (e.g. mouse click pressed) @@ -82,8 +82,7 @@ public: * @param framebuffer_x Framebuffer x-coordinate that was pressed * @param framebuffer_y Framebuffer y-coordinate that was pressed */ - static void TouchPressed(const FramebufferLayout& layout, unsigned framebuffer_x, - unsigned framebuffer_y); + void TouchPressed(const FramebufferLayout& layout, unsigned framebuffer_x, unsigned framebuffer_y); /** * Signal that a touch released event has occurred (e.g. mouse click released) @@ -91,8 +90,7 @@ public: * @param framebuffer_x Framebuffer x-coordinate that was released * @param framebuffer_y Framebuffer y-coordinate that was released */ - static void TouchReleased(const FramebufferLayout& layout, unsigned framebuffer_x, - unsigned framebuffer_y); + void TouchReleased(const FramebufferLayout& layout, unsigned framebuffer_x, unsigned framebuffer_y); /** * Signal that a touch movement event has occurred (e.g. mouse was moved over the emu window) @@ -100,8 +98,7 @@ public: * @param framebuffer_x Framebuffer x-coordinate * @param framebuffer_y Framebuffer y-coordinate */ - static void TouchMoved(const FramebufferLayout& layout, unsigned framebuffer_x, - unsigned framebuffer_y); + void TouchMoved(const FramebufferLayout& layout, unsigned framebuffer_x, unsigned framebuffer_y); /** * Returns currently active configuration. @@ -196,5 +193,5 @@ private: WindowConfig config; ///< Internal configuration (changes pending for being applied in ProcessConfigurationChanges) WindowConfig active_config; ///< Internal active configuration - static bool touch_pressed; ///< True if touchpad area is currently pressed, otherwise false + bool touch_pressed; ///< True if touchpad area is currently pressed, otherwise false }; -- cgit v1.2.3 From d61b26b79f889603a084e148626bba3c267cf75f Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 9 Mar 2015 00:14:59 -0400 Subject: HID: Complete refactor of pad/touch input to fix threading issues. --- src/common/emu_window.cpp | 74 ++++++++++++++++++----------------------------- src/common/emu_window.h | 57 ++++++++++++++++++++++-------------- 2 files changed, 63 insertions(+), 68 deletions(-) (limited to 'src/common') diff --git a/src/common/emu_window.cpp b/src/common/emu_window.cpp index 89bb89481..6516fc633 100644 --- a/src/common/emu_window.cpp +++ b/src/common/emu_window.cpp @@ -6,15 +6,11 @@ #include "video_core/video_core.h" void EmuWindow::KeyPressed(KeyMap::HostDeviceKey key) { - Service::HID::PadState mapped_key = KeyMap::GetPadKey(key); - - Service::HID::PadButtonPress(mapped_key); + pad_state.hex |= KeyMap::GetPadKey(key).hex; } void EmuWindow::KeyReleased(KeyMap::HostDeviceKey key) { - Service::HID::PadState mapped_key = KeyMap::GetPadKey(key); - - Service::HID::PadButtonRelease(mapped_key); + pad_state.hex &= ~KeyMap::GetPadKey(key).hex; } /** @@ -25,55 +21,41 @@ void EmuWindow::KeyReleased(KeyMap::HostDeviceKey key) { * @return True if the coordinates are within the touchpad, otherwise false */ static bool IsWithinTouchscreen(const EmuWindow::FramebufferLayout& layout, unsigned framebuffer_x, - unsigned framebuffer_y) { - - return (framebuffer_y >= layout.bottom_screen.top && - framebuffer_y < layout.bottom_screen.bottom && - framebuffer_x >= layout.bottom_screen.left && - framebuffer_x < layout.bottom_screen.right); + unsigned framebuffer_y) { + return (framebuffer_y >= layout.bottom_screen.top && + framebuffer_y < layout.bottom_screen.bottom && + framebuffer_x >= layout.bottom_screen.left && + framebuffer_x < layout.bottom_screen.right); } -void EmuWindow::TouchPressed(const FramebufferLayout& layout, unsigned framebuffer_x, - unsigned framebuffer_y) { +void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) { + if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) + return; - if (IsWithinTouchscreen(layout, framebuffer_x, framebuffer_y)) { - u16 touch_x = VideoCore::kScreenBottomWidth * (framebuffer_x - layout.bottom_screen.left) / - (layout.bottom_screen.right - layout.bottom_screen.left); - u16 touch_y = VideoCore::kScreenBottomHeight * (framebuffer_y - layout.bottom_screen.top) / - (layout.bottom_screen.bottom - layout.bottom_screen.top); + touch_x = VideoCore::kScreenBottomWidth * (framebuffer_x - framebuffer_layout.bottom_screen.left) / + (framebuffer_layout.bottom_screen.right - framebuffer_layout.bottom_screen.left); + touch_y = VideoCore::kScreenBottomHeight * (framebuffer_y - framebuffer_layout.bottom_screen.top) / + (framebuffer_layout.bottom_screen.bottom - framebuffer_layout.bottom_screen.top); - Service::HID::TouchPress(touch_x, touch_y); - Service::HID::TouchUpdateComplete(); - - touch_pressed = true; - } + touch_pressed = true; + pad_state.touch = 1; } -void EmuWindow::TouchReleased(const FramebufferLayout& layout, unsigned framebuffer_x, - unsigned framebuffer_y) { - - if (IsWithinTouchscreen(layout, framebuffer_x, framebuffer_y)) { - - Service::HID::TouchRelease(); - Service::HID::TouchUpdateComplete(); - - touch_pressed = false; - } +void EmuWindow::TouchReleased() { + touch_pressed = false; + touch_x = 0; + touch_y = 0; + pad_state.touch = 0; } -void EmuWindow::TouchMoved(const FramebufferLayout& layout, unsigned framebuffer_x, - unsigned framebuffer_y) { +void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) { + if (!touch_pressed) + return; - if (touch_pressed) { - if (IsWithinTouchscreen(layout, framebuffer_x, framebuffer_y)) { - EmuWindow::TouchPressed(layout, framebuffer_x, framebuffer_y); - } else { - Service::HID::TouchRelease(); - Service::HID::TouchUpdateComplete(); - - touch_pressed = false; - } - } + if (IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) + TouchPressed(framebuffer_x, framebuffer_y); + else + TouchReleased(); } EmuWindow::FramebufferLayout EmuWindow::FramebufferLayout::DefaultScreenLayout(unsigned width, diff --git a/src/common/emu_window.h b/src/common/emu_window.h index 8e4b510e9..2be7517bc 100644 --- a/src/common/emu_window.h +++ b/src/common/emu_window.h @@ -78,27 +78,41 @@ public: /** * Signal that a touch pressed event has occurred (e.g. mouse click pressed) - * @param layout FramebufferLayout object describing the framebuffer size and screen positions * @param framebuffer_x Framebuffer x-coordinate that was pressed * @param framebuffer_y Framebuffer y-coordinate that was pressed */ - void TouchPressed(const FramebufferLayout& layout, unsigned framebuffer_x, unsigned framebuffer_y); + void TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y); - /** - * Signal that a touch released event has occurred (e.g. mouse click released) - * @param layout FramebufferLayout object describing the framebuffer size and screen positions - * @param framebuffer_x Framebuffer x-coordinate that was released - * @param framebuffer_y Framebuffer y-coordinate that was released - */ - void TouchReleased(const FramebufferLayout& layout, unsigned framebuffer_x, unsigned framebuffer_y); + /// Signal that a touch released event has occurred (e.g. mouse click released) + void TouchReleased(); /** * Signal that a touch movement event has occurred (e.g. mouse was moved over the emu window) - * @param layout FramebufferLayout object describing the framebuffer size and screen positions * @param framebuffer_x Framebuffer x-coordinate * @param framebuffer_y Framebuffer y-coordinate */ - void TouchMoved(const FramebufferLayout& layout, unsigned framebuffer_x, unsigned framebuffer_y); + void TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y); + + /** + * Gets the current pad state (which buttons are pressed and the circle pad direction). + * @note This should be called by the core emu thread to get a state set by the window thread. + * @todo Fix this function to be thread-safe. + * @return PadState object indicating the current pad state + */ + const Service::HID::PadState GetPadState() const { + return pad_state; + } + + /** + * Gets the current touch screen state (touch X/Y coordinates and whether or not it is pressed). + * @note This should be called by the core emu thread to get a state set by the window thread. + * @todo Fix this function to be thread-safe. + * @return std::tuple of (x, y, pressed) where `x` and `y` are the touch coordinates and + * `pressed` is true if the touch screen is currently being pressed + */ + const std::tuple& GetTouchState() const { + return std::make_tuple(touch_x, touch_y, touch_pressed); + } /** * Returns currently active configuration. @@ -124,21 +138,15 @@ public: return framebuffer_layout; } - /** - * Gets window client area width in logical coordinates. - * @note For high-DPI systems, this is smaller than the framebuffer size. - * @note This method is thread-safe - */ - std::pair GetClientAreaSize() const { - return std::make_pair(client_area_width, client_area_height); - } - protected: - EmuWindow() - { + EmuWindow() { // TODO: Find a better place to set this. config.min_client_area_size = std::make_pair(400u, 480u); active_config = config; + pad_state.hex = 0; + touch_x = 0; + touch_y = 0; + touch_pressed = false; } virtual ~EmuWindow() {} @@ -194,4 +202,9 @@ private: WindowConfig active_config; ///< Internal active configuration bool touch_pressed; ///< True if touchpad area is currently pressed, otherwise false + + u16 touch_x; ///< Touchpad X-position in native 3DS pixel coordinates (0-320) + u16 touch_y; ///< Touchpad Y-position in native 3DS pixel coordinates (0-240) + + Service::HID::PadState pad_state; }; -- cgit v1.2.3