Преглед на файлове

Test adding touch simulation to SDL backend

Michael Ragazzon преди 3 месеца
родител
ревизия
5556ac74c5

+ 15 - 0
Backends/CMakeLists.txt

@@ -11,6 +11,21 @@ target_sources(rmlui_backend_common_headers INTERFACE
 	"${CMAKE_CURRENT_LIST_DIR}/RmlUi_Backend.h"
 	"${CMAKE_CURRENT_LIST_DIR}/RmlUi_Backend.h"
 )
 )
 
 
+if(RMLUI_BACKEND_SIMULATE_TOUCH)
+	set(RMLUI_BACKEND_SIMULATE_TOUCH_SUPPORTED
+		"SDL_GL2"
+		"SDL_GL3"
+		"SDL_VK"
+		"SDL_SDLrenderer"
+		"SDL_GPU"
+	)
+	if(NOT RMLUI_BACKEND IN_LIST RMLUI_BACKEND_SIMULATE_TOUCH_SUPPORTED)
+		message(WARNING "RMLUI_BACKEND_SIMULATE_TOUCH enabled but not supported on selected backend ${RMLUI_BACKEND}")
+	else()
+		target_compile_definitions(rmlui_backend_common_headers INTERFACE "RMLUI_BACKEND_SIMULATE_TOUCH")
+	endif()
+endif()
+
 add_library(rmlui_backend_Win32_GL2 INTERFACE)
 add_library(rmlui_backend_Win32_GL2 INTERFACE)
 target_sources(rmlui_backend_Win32_GL2 INTERFACE
 target_sources(rmlui_backend_Win32_GL2 INTERFACE
 	"${CMAKE_CURRENT_LIST_DIR}/RmlUi_Platform_Win32.cpp"
 	"${CMAKE_CURRENT_LIST_DIR}/RmlUi_Platform_Win32.cpp"

+ 7 - 0
Backends/RmlUi_Backend_SDL_GL2.cpp

@@ -147,6 +147,13 @@ bool Backend::Initialize(const char* window_name, int width, int height, bool al
 
 
 	// Submit click events when focusing the window.
 	// Submit click events when focusing the window.
 	SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
 	SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
+	// Touch events are handled natively, no need to generate synthetic mouse events for touch devices.
+	SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
+
+#if defined RMLUI_BACKEND_SIMULATE_TOUCH
+	// Simulate touch events from mouse events for testing touch behavior on a desktop machine.
+	SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "1");
+#endif
 
 
 	// Request stencil buffer of at least 8-bit size to supporting clipping on transformed elements.
 	// Request stencil buffer of at least 8-bit size to supporting clipping on transformed elements.
 	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
 	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);

+ 7 - 0
Backends/RmlUi_Backend_SDL_GL3.cpp

@@ -152,6 +152,13 @@ bool Backend::Initialize(const char* window_name, int width, int height, bool al
 
 
 	// Submit click events when focusing the window.
 	// Submit click events when focusing the window.
 	SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
 	SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
+	// Touch events are handled natively, no need to generate synthetic mouse events for touch devices.
+	SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
+
+#if defined RMLUI_BACKEND_SIMULATE_TOUCH
+	// Simulate touch events from mouse events for testing touch behavior on a desktop machine.
+	SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "1");
+#endif
 
 
 #if defined RMLUI_PLATFORM_EMSCRIPTEN
 #if defined RMLUI_PLATFORM_EMSCRIPTEN
 	// GLES 3.0 (WebGL 2.0)
 	// GLES 3.0 (WebGL 2.0)

+ 8 - 0
Backends/RmlUi_Backend_SDL_GPU.cpp

@@ -63,7 +63,15 @@ bool Backend::Initialize(const char* window_name, int width, int height, bool al
 	if (!SDL_Init(SDL_INIT_VIDEO))
 	if (!SDL_Init(SDL_INIT_VIDEO))
 		return false;
 		return false;
 
 
+	// Submit click events when focusing the window.
 	SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
 	SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
+	// Touch events are handled natively, no need to generate synthetic mouse events for touch devices.
+	SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
+
+#if defined RMLUI_BACKEND_SIMULATE_TOUCH
+	// Simulate touch events from mouse events for testing touch behavior on a desktop machine.
+	SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "1");
+#endif
 
 
 	const float window_size_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
 	const float window_size_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
 	SDL_PropertiesID props = SDL_CreateProperties();
 	SDL_PropertiesID props = SDL_CreateProperties();

+ 7 - 0
Backends/RmlUi_Backend_SDL_SDLrenderer.cpp

@@ -65,6 +65,13 @@ bool Backend::Initialize(const char* window_name, int width, int height, bool al
 
 
 	// Submit click events when focusing the window.
 	// Submit click events when focusing the window.
 	SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
 	SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
+	// Touch events are handled natively, no need to generate synthetic mouse events for touch devices.
+	SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
+
+#if defined RMLUI_BACKEND_SIMULATE_TOUCH
+	// Simulate touch events from mouse events for testing touch behavior on a desktop machine.
+	SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "1");
+#endif
 
 
 #if SDL_MAJOR_VERSION >= 3
 #if SDL_MAJOR_VERSION >= 3
 	const float window_size_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
 	const float window_size_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());

+ 7 - 0
Backends/RmlUi_Backend_SDL_VK.cpp

@@ -73,6 +73,13 @@ bool Backend::Initialize(const char* window_name, int width, int height, bool al
 
 
 	// Submit click events when focusing the window.
 	// Submit click events when focusing the window.
 	SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
 	SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
+	// Touch events are handled natively, no need to generate synthetic mouse events for touch devices.
+	SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
+
+#if defined RMLUI_BACKEND_SIMULATE_TOUCH
+	// Simulate touch events from mouse events for testing touch behavior on a desktop machine.
+	SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "1");
+#endif
 
 
 #if SDL_MAJOR_VERSION >= 3
 #if SDL_MAJOR_VERSION >= 3
 	const float window_size_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
 	const float window_size_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());

+ 40 - 5
Backends/RmlUi_Platform_SDL.cpp

@@ -32,6 +32,12 @@
 #include <RmlUi/Core/StringUtilities.h>
 #include <RmlUi/Core/StringUtilities.h>
 #include <RmlUi/Core/SystemInterface.h>
 #include <RmlUi/Core/SystemInterface.h>
 
 
+static Rml::TouchList TouchEventToTouchList(SDL_Event& ev, Rml::Context* context, SDL_FingerID finger_id)
+{
+	const Rml::Vector2f position = Rml::Vector2f{ev.tfinger.x, ev.tfinger.y} * Rml::Vector2f{context->GetDimensions()};
+	return {Rml::Touch{static_cast<Rml::TouchId>(finger_id), position}};
+}
+
 SystemInterface_SDL::SystemInterface_SDL()
 SystemInterface_SDL::SystemInterface_SDL()
 {
 {
 #if SDL_MAJOR_VERSION >= 3
 #if SDL_MAJOR_VERSION >= 3
@@ -153,6 +159,8 @@ bool RmlSDL::InputEventHandler(Rml::Context* context, SDL_Window* window, SDL_Ev
 	#define RMLSDL_WINDOW_EVENTS_BEGIN
 	#define RMLSDL_WINDOW_EVENTS_BEGIN
 	#define RMLSDL_WINDOW_EVENTS_END
 	#define RMLSDL_WINDOW_EVENTS_END
 	auto GetKey = [](const SDL_Event& event) { return event.key.key; };
 	auto GetKey = [](const SDL_Event& event) { return event.key.key; };
+	auto GetPixelDensity = [](SDL_Window* target_window) { return SDL_GetWindowPixelDensity(target_window); };
+	auto GetFingerId = [](const SDL_Event& event) { return event.tfinger.fingerID; };
 	constexpr auto event_mouse_motion = SDL_EVENT_MOUSE_MOTION;
 	constexpr auto event_mouse_motion = SDL_EVENT_MOUSE_MOTION;
 	constexpr auto event_mouse_down = SDL_EVENT_MOUSE_BUTTON_DOWN;
 	constexpr auto event_mouse_down = SDL_EVENT_MOUSE_BUTTON_DOWN;
 	constexpr auto event_mouse_up = SDL_EVENT_MOUSE_BUTTON_UP;
 	constexpr auto event_mouse_up = SDL_EVENT_MOUSE_BUTTON_UP;
@@ -162,6 +170,10 @@ bool RmlSDL::InputEventHandler(Rml::Context* context, SDL_Window* window, SDL_Ev
 	constexpr auto event_text_input = SDL_EVENT_TEXT_INPUT;
 	constexpr auto event_text_input = SDL_EVENT_TEXT_INPUT;
 	constexpr auto event_window_size_changed = SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED;
 	constexpr auto event_window_size_changed = SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED;
 	constexpr auto event_window_leave = SDL_EVENT_WINDOW_MOUSE_LEAVE;
 	constexpr auto event_window_leave = SDL_EVENT_WINDOW_MOUSE_LEAVE;
+	constexpr auto event_finger_down = SDL_EVENT_FINGER_DOWN;
+	constexpr auto event_finger_up = SDL_EVENT_FINGER_UP;
+	constexpr auto event_finger_motion = SDL_EVENT_FINGER_MOTION;
+
 	constexpr auto rmlsdl_true = true;
 	constexpr auto rmlsdl_true = true;
 	constexpr auto rmlsdl_false = false;
 	constexpr auto rmlsdl_false = false;
 #else
 #else
@@ -176,6 +188,8 @@ bool RmlSDL::InputEventHandler(Rml::Context* context, SDL_Window* window, SDL_Ev
 		}                            \
 		}                            \
 		break;
 		break;
 	auto GetKey = [](const SDL_Event& event) { return event.key.keysym.sym; };
 	auto GetKey = [](const SDL_Event& event) { return event.key.keysym.sym; };
+	auto GetPixelDensity = [](SDL_Window* /*target_window*/) { return 1.f; };
+	auto GetFingerId = [](const SDL_Event& event) { return event.tfinger.fingerId; };
 	constexpr auto event_mouse_motion = SDL_MOUSEMOTION;
 	constexpr auto event_mouse_motion = SDL_MOUSEMOTION;
 	constexpr auto event_mouse_down = SDL_MOUSEBUTTONDOWN;
 	constexpr auto event_mouse_down = SDL_MOUSEBUTTONDOWN;
 	constexpr auto event_mouse_up = SDL_MOUSEBUTTONUP;
 	constexpr auto event_mouse_up = SDL_MOUSEBUTTONUP;
@@ -185,6 +199,10 @@ bool RmlSDL::InputEventHandler(Rml::Context* context, SDL_Window* window, SDL_Ev
 	constexpr auto event_text_input = SDL_TEXTINPUT;
 	constexpr auto event_text_input = SDL_TEXTINPUT;
 	constexpr auto event_window_size_changed = SDL_WINDOWEVENT_SIZE_CHANGED;
 	constexpr auto event_window_size_changed = SDL_WINDOWEVENT_SIZE_CHANGED;
 	constexpr auto event_window_leave = SDL_WINDOWEVENT_LEAVE;
 	constexpr auto event_window_leave = SDL_WINDOWEVENT_LEAVE;
+	constexpr auto event_finger_down = SDL_FINGERDOWN;
+	constexpr auto event_finger_up = SDL_FINGERUP;
+	constexpr auto event_finger_motion = SDL_FINGERMOTION;
+
 	constexpr auto rmlsdl_true = SDL_TRUE;
 	constexpr auto rmlsdl_true = SDL_TRUE;
 	constexpr auto rmlsdl_false = SDL_FALSE;
 	constexpr auto rmlsdl_false = SDL_FALSE;
 #endif
 #endif
@@ -193,13 +211,10 @@ bool RmlSDL::InputEventHandler(Rml::Context* context, SDL_Window* window, SDL_Ev
 
 
 	switch (ev.type)
 	switch (ev.type)
 	{
 	{
+#ifndef RMLUI_BACKEND_SIMULATE_TOUCH
 	case event_mouse_motion:
 	case event_mouse_motion:
 	{
 	{
-#if SDL_MAJOR_VERSION >= 3
-		const float pixel_density = SDL_GetWindowPixelDensity(window);
-#else
-		constexpr float pixel_density = 1.f;
-#endif
+		const float pixel_density = GetPixelDensity(window);
 		result = context->ProcessMouseMove(int(ev.motion.x * pixel_density), int(ev.motion.y * pixel_density), GetKeyModifierState());
 		result = context->ProcessMouseMove(int(ev.motion.x * pixel_density), int(ev.motion.y * pixel_density), GetKeyModifierState());
 	}
 	}
 	break;
 	break;
@@ -215,6 +230,8 @@ bool RmlSDL::InputEventHandler(Rml::Context* context, SDL_Window* window, SDL_Ev
 		result = context->ProcessMouseButtonUp(ConvertMouseButton(ev.button.button), GetKeyModifierState());
 		result = context->ProcessMouseButtonUp(ConvertMouseButton(ev.button.button), GetKeyModifierState());
 	}
 	}
 	break;
 	break;
+#endif
+
 	case event_mouse_wheel:
 	case event_mouse_wheel:
 	{
 	{
 		result = context->ProcessMouseWheel(float(-ev.wheel.y), GetKeyModifierState());
 		result = context->ProcessMouseWheel(float(-ev.wheel.y), GetKeyModifierState());
@@ -236,6 +253,24 @@ bool RmlSDL::InputEventHandler(Rml::Context* context, SDL_Window* window, SDL_Ev
 	{
 	{
 		result = context->ProcessTextInput(Rml::String(&ev.text.text[0]));
 		result = context->ProcessTextInput(Rml::String(&ev.text.text[0]));
 	}
 	}
+	break;
+	case event_finger_down:
+	{
+		const Rml::TouchList touches = TouchEventToTouchList(ev, context, GetFingerId(ev));
+		result = context->ProcessTouchStart(touches, GetKeyModifierState());
+	}
+	break;
+	case event_finger_motion:
+	{
+		const Rml::TouchList touches = TouchEventToTouchList(ev, context, GetFingerId(ev));
+		result = context->ProcessTouchMove(touches, GetKeyModifierState());
+	}
+	break;
+	case event_finger_up:
+	{
+		const Rml::TouchList touches = TouchEventToTouchList(ev, context, GetFingerId(ev));
+		result = context->ProcessTouchEnd(touches, GetKeyModifierState());
+	}
 	break;
 	break;
 
 
 		RMLSDL_WINDOW_EVENTS_BEGIN
 		RMLSDL_WINDOW_EVENTS_BEGIN

+ 1 - 0
CMakeLists.txt

@@ -24,6 +24,7 @@ option(BUILD_SHARED_LIBS "CMake standard option. Choose whether to build shared
 #   - Do not include negations (such as "not" and "disable"), to avoid situations with double negation.
 #   - Do not include negations (such as "not" and "disable"), to avoid situations with double negation.
 #   - Do not include a verb prefix (such as "enable" and "build"), as these are often superfluous.
 #   - Do not include a verb prefix (such as "enable" and "build"), as these are often superfluous.
 option(RMLUI_SAMPLES "Build samples of the library." OFF)
 option(RMLUI_SAMPLES "Build samples of the library." OFF)
+option(RMLUI_BACKEND_SIMULATE_TOUCH "Simulate touch events with mouse events" OFF)
 set(RMLUI_BACKEND "auto" CACHE STRING "Backend to use when building the RmlUi samples. Choose one from ./CMake/OptionsLists.cmake.")
 set(RMLUI_BACKEND "auto" CACHE STRING "Backend to use when building the RmlUi samples. Choose one from ./CMake/OptionsLists.cmake.")
 set_property(CACHE RMLUI_BACKEND PROPERTY STRINGS ${RMLUI_BACKEND_OPTIONS})
 set_property(CACHE RMLUI_BACKEND PROPERTY STRINGS ${RMLUI_BACKEND_OPTIONS})
 if(NOT RMLUI_BACKEND IN_LIST RMLUI_BACKEND_OPTIONS)
 if(NOT RMLUI_BACKEND IN_LIST RMLUI_BACKEND_OPTIONS)

+ 9 - 8
readme.md

@@ -156,17 +156,18 @@ The provided backends on the other hand are not intended to be used directly by
 
 
 ### Platforms
 ### Platforms
 
 
-| Platform support | Basic windowing | Clipboard | High DPI | Comments  |
-|------------------|:---------------:|:---------:|:--------:|-----------|
-| Win32            |       ✔️        |    ✔️     |    ✔️    | High DPI only supported on Windows 10 and newer. |
-| X11              |       ✔️        |    ✔️     |    ❌     |  |
-| SFML             |       ✔️        |    ⚠️     |    ❌     | Supports SFML 2 and SFML 3. Some issues with Unicode characters in clipboard. |
-| GLFW             |       ✔️        |    ✔️     |    ✔️    |  |
-| SDL              |       ✔️        |    ✔️     |    ✔️    | Supports SDL 2 and SDL 3. High DPI supported only on SDL 3. |
+| Platform | Basic windowing | Clipboard | High DPI | Touch | Comments                                                                      |
+|----------|:---------------:|:---------:|:--------:|:-----:|-------------------------------------------------------------------------------|
+| Win32    |       ✔️        |    ✔️     |    ✔️    |   ❌   | High DPI only supported on Windows 10 and newer.                              |
+| X11      |       ✔️        |    ✔️     |    ❌     |   ❌   |                                                                               |
+| SFML     |       ✔️        |    ⚠️     |    ❌     |   ❌   | Supports SFML 2 and SFML 3. Some issues with Unicode characters in clipboard. |
+| GLFW     |       ✔️        |    ✔️     |    ✔️    |   ❌   |                                                                               |
+| SDL      |       ✔️        |    ✔️     |    ✔️    |  ✔️   | Supports SDL 2 and SDL 3. High DPI supported only on SDL 3.                   |
 
 
 **Basic windowing**: Open windows, react to resize events, submit inputs to the RmlUi context.\
 **Basic windowing**: Open windows, react to resize events, submit inputs to the RmlUi context.\
 **Clipboard**: Read from and write to the system clipboard.\
 **Clipboard**: Read from and write to the system clipboard.\
-**High DPI**: Scale the [dp-ratio](https://mikke89.github.io/RmlUiDoc/pages/rcss/syntax#dp-unit) of RmlUi contexts based on the monitor's DPI settings. React to DPI-changes, either because of changed settings or when moving the window to another monitor.
+**High DPI**: Scale the [dp-ratio](https://mikke89.github.io/RmlUiDoc/pages/rcss/syntax#dp-unit) of RmlUi contexts based on the monitor's DPI settings. React to DPI-changes, either because of changed settings or when moving the window to another monitor. \
+**Touch**: Process touch events, enable dragging and inertial scrolling with touch movement.
 
 
 ### Backends
 ### Backends