fix scroll direction: use RmlUi native touch API

Switch from mouse event emulation to RmlUi's native touch API
(ProcessTouchStart/Move/End) for natural scrolling behavior.

When dragging on scrollable content, the content now follows
the finger/cursor direction instead of scrolling in reverse.

- Designer: Use touch API when left mouse button is pressed
- Android kernel: Use touch API for all touch events
This commit is contained in:
2026-01-20 20:30:08 +01:00
parent bd8ce61897
commit cbc03c0674
2 changed files with 39 additions and 8 deletions

View File

@@ -59,6 +59,11 @@ static std::string g_test_output_path; // Output file for record/screenshot/hie
static mosis::testing::ActionRecorder* g_action_recorder = nullptr; static mosis::testing::ActionRecorder* g_action_recorder = nullptr;
static mosis::testing::ActionPlayer* g_action_player = nullptr; static mosis::testing::ActionPlayer* g_action_player = nullptr;
// Touch simulation state for natural scrolling behavior
static bool g_touch_active = false;
static int g_touch_start_x = 0;
static int g_touch_start_y = 0;
// Logging and hierarchy dump for testing // Logging and hierarchy dump for testing
static std::string g_log_file_path; // Log file path (--log) static std::string g_log_file_path; // Log file path (--log)
static std::string g_hierarchy_file_path; // Continuous hierarchy dump path (--hierarchy) static std::string g_hierarchy_file_path; // Continuous hierarchy dump path (--hierarchy)
@@ -211,12 +216,20 @@ static void MouseButtonCallback(GLFWwindow* window, int button, int action, int
if (g_action_recorder && g_action_recorder->IsRecording()) { if (g_action_recorder && g_action_recorder->IsRecording()) {
g_action_recorder->RecordMouseDown(mouseX, mouseY); g_action_recorder->RecordMouseDown(mouseX, mouseY);
} }
g_context->ProcessMouseButtonDown(0, key_modifier); // Use touch API for natural scrolling behavior
g_touch_active = true;
g_touch_start_x = mouseX;
g_touch_start_y = mouseY;
Rml::TouchList touches = {{0, Rml::Vector2f(static_cast<float>(mouseX), static_cast<float>(mouseY))}};
g_context->ProcessTouchStart(touches, 0);
} else if (action == GLFW_RELEASE) { } else if (action == GLFW_RELEASE) {
if (g_action_recorder && g_action_recorder->IsRecording()) { if (g_action_recorder && g_action_recorder->IsRecording()) {
g_action_recorder->RecordMouseUp(mouseX, mouseY); g_action_recorder->RecordMouseUp(mouseX, mouseY);
} }
g_context->ProcessMouseButtonUp(0, key_modifier); // End touch for natural scrolling
g_touch_active = false;
Rml::TouchList touches = {{0, Rml::Vector2f(static_cast<float>(mouseX), static_cast<float>(mouseY))}};
g_context->ProcessTouchEnd(touches, 0);
} }
} }
} }
@@ -234,7 +247,14 @@ static void CursorPosCallback(GLFWwindow* window, double xpos, double ypos) {
int mouseX = static_cast<int>(xpos * fbWidth / winWidth); int mouseX = static_cast<int>(xpos * fbWidth / winWidth);
int mouseY = static_cast<int>(ypos * fbHeight / winHeight); int mouseY = static_cast<int>(ypos * fbHeight / winHeight);
// Always update mouse position for hover effects
g_context->ProcessMouseMove(mouseX, mouseY, 0); g_context->ProcessMouseMove(mouseX, mouseY, 0);
// If touch is active (left button pressed), also send touch move for natural scrolling
if (g_touch_active) {
Rml::TouchList touches = {{0, Rml::Vector2f(static_cast<float>(mouseX), static_cast<float>(mouseY))}};
g_context->ProcessTouchMove(touches, 0);
}
} }
static void ScrollCallback(GLFWwindow* window, double xoffset, double yoffset) { static void ScrollCallback(GLFWwindow* window, double xoffset, double yoffset) {

View File

@@ -761,9 +761,13 @@ void Kernel::on_touch_down(float x, float y)
m_tasks.emplace_back([x, y](Rml::Context* context){ m_tasks.emplace_back([x, y](Rml::Context* context){
int px = static_cast<int>(x * 540); int px = static_cast<int>(x * 540);
int py = static_cast<int>(y * 960); int py = static_cast<int>(y * 960);
bool move_handled = context->ProcessMouseMove(px, py, 0);
bool down_handled = context->ProcessMouseButtonDown(0, 0); // Use native touch API for proper scroll direction (natural scrolling)
Logger::Log(std::format("Touch at ({}, {}): move={}, down={}", px, py, move_handled, down_handled)); // Touch ID 0 for primary touch point
Rml::TouchList touches = {{0, Rml::Vector2f(static_cast<float>(px), static_cast<float>(py))}};
context->ProcessTouchStart(touches, 0);
Logger::Log(std::format("Touch start at ({}, {})", px, py));
// Debug: Check if there's a hover element // Debug: Check if there's a hover element
auto* hover_elem = context->GetHoverElement(); auto* hover_elem = context->GetHoverElement();
@@ -782,7 +786,11 @@ void Kernel::on_touch_move(float x, float y)
Logger::Log(std::format("on_touch_move {} - {}", x, y)); Logger::Log(std::format("on_touch_move {} - {}", x, y));
std::lock_guard _lock(m_mutex); std::lock_guard _lock(m_mutex);
m_tasks.emplace_back([x, y](Rml::Context* context){ m_tasks.emplace_back([x, y](Rml::Context* context){
context->ProcessMouseMove(static_cast<int>(x * 540), static_cast<int>(y * 960), 0); int px = static_cast<int>(x * 540);
int py = static_cast<int>(y * 960);
// Use native touch API for proper scroll direction
Rml::TouchList touches = {{0, Rml::Vector2f(static_cast<float>(px), static_cast<float>(py))}};
context->ProcessTouchMove(touches, 0);
}); });
} }
@@ -791,8 +799,11 @@ void Kernel::on_touch_up(float x, float y)
Logger::Log(std::format("on_touch_up {} - {}", x, y)); Logger::Log(std::format("on_touch_up {} - {}", x, y));
std::lock_guard _lock(m_mutex); std::lock_guard _lock(m_mutex);
m_tasks.emplace_back([x, y](Rml::Context* context){ m_tasks.emplace_back([x, y](Rml::Context* context){
context->ProcessMouseMove(static_cast<int>(x * 540), static_cast<int>(y * 960), 0); int px = static_cast<int>(x * 540);
context->ProcessMouseButtonUp(0, 0); int py = static_cast<int>(y * 960);
// Use native touch API for proper scroll direction
Rml::TouchList touches = {{0, Rml::Vector2f(static_cast<float>(px), static_cast<float>(py))}};
context->ProcessTouchEnd(touches, 0);
}); });
} }