summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/sdl/osdsdl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/sdl/osdsdl.cpp')
-rw-r--r--src/osd/sdl/osdsdl.cpp244
1 files changed, 185 insertions, 59 deletions
diff --git a/src/osd/sdl/osdsdl.cpp b/src/osd/sdl/osdsdl.cpp
index 2d3e5e4f02c..87af652733e 100644
--- a/src/osd/sdl/osdsdl.cpp
+++ b/src/osd/sdl/osdsdl.cpp
@@ -17,8 +17,8 @@
#include "ui/uimain.h"
-#include <SDL2/SDL.h>
-
+#include <algorithm>
+#include <cmath>
#include <cstdio>
#include <cstring>
@@ -168,7 +168,9 @@ sdl_osd_interface::sdl_osd_interface(sdl_options &options) :
m_modifier_keys(0),
m_last_click_time(std::chrono::steady_clock::time_point::min()),
m_last_click_x(0),
- m_last_click_y(0)
+ m_last_click_y(0),
+ m_enable_touch(false),
+ m_next_ptrdev(0)
{
}
@@ -260,6 +262,34 @@ void sdl_osd_interface::init(running_machine &machine)
}
}
+ /* do we want touch support or will we use mouse emulation? */
+ m_enable_touch = options().enable_touch();
+ try
+ {
+ if (m_enable_touch)
+ {
+ int const count(SDL_GetNumTouchDevices());
+ m_ptrdev_map.reserve(std::max<int>(count + 1, 8));
+ map_pointer_device(SDL_MOUSE_TOUCHID);
+ for (int i = 0; count > i; ++i)
+ {
+ SDL_TouchID const device(SDL_GetTouchDevice(i));
+ if (device)
+ map_pointer_device(device);
+ }
+ }
+ else
+ {
+ m_ptrdev_map.reserve(1);
+ map_pointer_device(SDL_MOUSE_TOUCHID);
+ }
+ }
+ catch (std::bad_alloc const &)
+ {
+ osd_printf_error("sdl_osd_interface: error allocating pointer data\n");
+ // survivable - it will still attempt to allocate mappings when it first sees devices
+ }
+
#if defined(SDLMAME_ANDROID)
SDL_SetHint(SDL_HINT_VIDEO_EXTERNAL_CONTEXT, "1");
#endif
@@ -502,74 +532,126 @@ void sdl_osd_interface::process_events()
break;
case SDL_MOUSEMOTION:
+ if (!m_enable_touch || (SDL_TOUCH_MOUSEID != event.motion.which))
{
- int cx, cy;
- auto const window = focus_window(event.motion);
- if (window && window->xy_to_render_target(event.motion.x, event.motion.y, &cx, &cy))
- machine().ui_input().push_mouse_move_event(window->target(), cx, cy);
+ auto const window = window_from_id(event.motion.windowID);
+ if (!window)
+ break;
+
+ unsigned device;
+ try
+ {
+ device = map_pointer_device(SDL_MOUSE_TOUCHID);
+ }
+ catch (std::bad_alloc const &)
+ {
+ osd_printf_error("sdl_osd_interface: error allocating pointer data\n");
+ break;
+ }
+
+ int x, y;
+ window->xy_to_render_target(event.motion.x, event.motion.y, &x, &y);
+ window->mouse_moved(device, x, y);
}
break;
case SDL_MOUSEBUTTONDOWN:
- //printf("But down %d %d %d %d %s\n", event.button.which, event.button.button, event.button.x, event.button.y, devinfo->name.c_str());
- if (event.button.button == 1)
+ case SDL_MOUSEBUTTONUP:
+ if (!m_enable_touch || (SDL_TOUCH_MOUSEID != event.button.which))
+ {
+ auto const window = window_from_id(event.button.windowID);
+ if (!window)
+ break;
+
+ unsigned device;
+ try
+ {
+ device = map_pointer_device(SDL_MOUSE_TOUCHID);
+ }
+ catch (std::bad_alloc const &)
+ {
+ osd_printf_error("sdl_osd_interface: error allocating pointer data\n");
+ break;
+ }
+
+ int x, y;
+ window->xy_to_render_target(event.button.x, event.button.y, &x, &y);
+ unsigned button(event.button.button - 1);
+ if ((1 == button) || (2 == button))
+ button ^= 3;
+ if (SDL_PRESSED == event.button.state)
+ window->mouse_down(device, x, y, button);
+ else
+ window->mouse_up(device, x, y, button);
+ }
+ break;
+
+ case SDL_MOUSEWHEEL:
{
- int cx, cy;
- auto const window = focus_window(event.button);
- if (window && window->xy_to_render_target(event.button.x, event.button.y, &cx, &cy))
+ auto const window = window_from_id(event.wheel.windowID);
+ if (window)
{
- auto const double_click_speed = std::chrono::milliseconds(250);
- auto const click = std::chrono::steady_clock::now();
- machine().ui_input().push_mouse_down_event(window->target(), cx, cy);
-
- // avoid overflow with std::chrono::time_point::min() by adding rather than subtracting
- if (click < (m_last_click_time + double_click_speed)
- && (cx >= (m_last_click_x - 4) && cx <= (m_last_click_x + 4))
- && (cy >= (m_last_click_y - 4) && cy <= (m_last_click_y + 4)))
+ unsigned device;
+ try
{
- m_last_click_time = std::chrono::time_point<std::chrono::steady_clock>::min();
- machine().ui_input().push_mouse_double_click_event(window->target(), cx, cy);
+ device = map_pointer_device(SDL_MOUSE_TOUCHID);
}
- else
+ catch (std::bad_alloc const &)
{
- m_last_click_time = click;
- m_last_click_x = cx;
- m_last_click_y = cy;
+ osd_printf_error("sdl_osd_interface: error allocating pointer data\n");
+ break;
}
+#if SDL_VERSION_ATLEAST(2, 0, 18)
+ window->mouse_wheel(device, std::lround(event.wheel.preciseY * 120));
+#else
+ window->mouse_wheel(device, event.wheel.y);
+#endif
}
}
- else if (event.button.button == 3)
- {
- int cx, cy;
- auto const window = focus_window(event.button);
- if (window != nullptr && window->xy_to_render_target(event.button.x, event.button.y, &cx, &cy))
- machine().ui_input().push_mouse_rdown_event(window->target(), cx, cy);
- }
break;
- case SDL_MOUSEBUTTONUP:
- //printf("But up %d %d %d %d\n", event.button.which, event.button.button, event.button.x, event.button.y);
- if (event.button.button == 1)
+ case SDL_FINGERMOTION:
+ case SDL_FINGERDOWN:
+ case SDL_FINGERUP:
+ if (m_enable_touch && (SDL_MOUSE_TOUCHID != event.tfinger.touchId))
{
- int cx, cy;
- auto const window = focus_window(event.button);
- if (window && window->xy_to_render_target(event.button.x, event.button.y, &cx, &cy))
- machine().ui_input().push_mouse_up_event(window->target(), cx, cy);
- }
- else if (event.button.button == 3)
- {
- int cx, cy;
- auto window = focus_window(event.button);
- if (window && window->xy_to_render_target(event.button.x, event.button.y, &cx, &cy))
- machine().ui_input().push_mouse_rup_event(window->target(), cx, cy);
- }
- break;
+ // ignore if it doesn't map to a window we own
+ auto const window = window_from_id(event.tfinger.windowID);
+ if (!window)
+ break;
+
+ // map SDL touch device ID to a zero-based device number
+ unsigned device;
+ try
+ {
+ device = map_pointer_device(event.tfinger.touchId);
+ }
+ catch (std::bad_alloc const &)
+ {
+ osd_printf_error("sdl_osd_interface: error allocating pointer data\n");
+ break;
+ }
- case SDL_MOUSEWHEEL:
- {
- auto const window = focus_window(event.wheel);
- if (window)
- machine().ui_input().push_mouse_wheel_event(window->target(), 0, 0, event.wheel.y, 3);
+ // convert normalised coordinates to what MAME wants
+ auto const size = window->get_size();
+ int const winx = std::lround(event.tfinger.x * size.width());
+ int const winy = std::lround(event.tfinger.y * size.height());
+ int x, y;
+ window->xy_to_render_target(winx, winy, &x, &y);
+
+ // call appropriate window method
+ switch (event.type)
+ {
+ case SDL_FINGERMOTION:
+ window->finger_moved(event.tfinger.fingerId, device, x, y);
+ break;
+ case SDL_FINGERDOWN:
+ window->finger_down(event.tfinger.fingerId, device, x, y);
+ break;
+ case SDL_FINGERUP:
+ window->finger_up(event.tfinger.fingerId, device, x, y);
+ break;
+ }
}
break;
}
@@ -626,12 +708,37 @@ void sdl_osd_interface::process_window_event(SDL_Event const &event)
break;
case SDL_WINDOWEVENT_ENTER:
- m_mouse_over_window = 1;
+ {
+ m_mouse_over_window = 1;
+ unsigned device;
+ try
+ {
+ device = map_pointer_device(SDL_MOUSE_TOUCHID);
+ }
+ catch (std::bad_alloc const &)
+ {
+ osd_printf_error("sdl_osd_interface: error allocating pointer data\n");
+ break;
+ }
+ window->mouse_entered(device);
+ }
break;
case SDL_WINDOWEVENT_LEAVE:
- machine().ui_input().push_mouse_leave_event(window->target());
- m_mouse_over_window = 0;
+ {
+ m_mouse_over_window = 0;
+ unsigned device;
+ try
+ {
+ device = map_pointer_device(SDL_MOUSE_TOUCHID);
+ }
+ catch (std::bad_alloc const &)
+ {
+ osd_printf_error("sdl_osd_interface: error allocating pointer data\n");
+ break;
+ }
+ window->mouse_left(device);
+ }
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
@@ -717,9 +824,28 @@ void sdl_osd_interface::check_osd_inputs()
template <typename T>
sdl_window_info *sdl_osd_interface::focus_window(T const &event) const
{
- // FIXME: SDL does not properly report the window for certain OS.
- if (false)
+ // FIXME: SDL does not properly report the window for certain versions of Ubuntu - is this still relevant?
+ if (m_enable_touch)
return window_from_id(event.windowID);
else
return m_focus_window;
}
+
+
+unsigned sdl_osd_interface::map_pointer_device(SDL_TouchID device)
+{
+ auto devpos(std::lower_bound(
+ m_ptrdev_map.begin(),
+ m_ptrdev_map.end(),
+ device,
+ [] (std::pair<SDL_TouchID, unsigned> const &mapping, SDL_TouchID id)
+ {
+ return mapping.first < id;
+ }));
+ if ((m_ptrdev_map.end() == devpos) || (device != devpos->first))
+ {
+ devpos = m_ptrdev_map.emplace(devpos, device, m_next_ptrdev);
+ ++m_next_ptrdev;
+ }
+ return devpos->second;
+}