From e6432041b2102ca957d02e22f9a7c93897d8ed27 Mon Sep 17 00:00:00 2001 From: Alex Studer Date: Sun, 7 Jul 2024 01:26:04 -0400 Subject: [PATCH] Android: Pass touch events through as mouse events This is probably not the best way of handling touch events, but at least it allows the user to actually interact with the page! --- .../main/cpp/WebViewImplementationNative.cpp | 19 ++++++++++++++ .../main/cpp/WebViewImplementationNative.h | 2 ++ .../cpp/WebViewImplementationNativeJNI.cpp | 26 +++++++++++++++++++ .../java/org/serenityos/ladybird/WebView.kt | 18 +++++++++++++ .../ladybird/WebViewImplementation.kt | 6 +++++ 5 files changed, 71 insertions(+) diff --git a/Ladybird/Android/src/main/cpp/WebViewImplementationNative.cpp b/Ladybird/Android/src/main/cpp/WebViewImplementationNative.cpp index f65ed5529f7..e001104a8d7 100644 --- a/Ladybird/Android/src/main/cpp/WebViewImplementationNative.cpp +++ b/Ladybird/Android/src/main/cpp/WebViewImplementationNative.cpp @@ -103,6 +103,25 @@ void WebViewImplementationNative::set_device_pixel_ratio(float f) client().async_set_device_pixels_per_css_pixel(0, m_device_pixel_ratio); } +void WebViewImplementationNative::mouse_event(Web::MouseEvent::Type event_type, float x, float y, float raw_x, float raw_y) +{ + Gfx::IntPoint position = { x, y }; + Gfx::IntPoint screen_position = { raw_x, raw_y }; + auto event = Web::MouseEvent { + event_type, + position.to_type(), + screen_position.to_type(), + Web::UIEvents::MouseButton::Primary, + Web::UIEvents::MouseButton::Primary, + Web::UIEvents::KeyModifier::Mod_None, + 0, + 0, + nullptr + }; + + enqueue_input_event(move(event)); +} + NonnullRefPtr WebViewImplementationNative::bind_web_content_client() { JavaEnvironment env(global_vm); diff --git a/Ladybird/Android/src/main/cpp/WebViewImplementationNative.h b/Ladybird/Android/src/main/cpp/WebViewImplementationNative.h index dfbe3f195b9..365598ea16d 100644 --- a/Ladybird/Android/src/main/cpp/WebViewImplementationNative.h +++ b/Ladybird/Android/src/main/cpp/WebViewImplementationNative.h @@ -29,6 +29,8 @@ public: void set_viewport_geometry(int w, int h); void set_device_pixel_ratio(float f); + void mouse_event(Web::MouseEvent::Type event_type, float x, float y, float raw_x, float raw_y); + static jclass global_class_reference; static jmethodID bind_webcontent_method; static jmethodID invalidate_layout_method; diff --git a/Ladybird/Android/src/main/cpp/WebViewImplementationNativeJNI.cpp b/Ladybird/Android/src/main/cpp/WebViewImplementationNativeJNI.cpp index 6af71e0b921..be3f9cce869 100644 --- a/Ladybird/Android/src/main/cpp/WebViewImplementationNativeJNI.cpp +++ b/Ladybird/Android/src/main/cpp/WebViewImplementationNativeJNI.cpp @@ -93,3 +93,29 @@ Java_org_serenityos_ladybird_WebViewImplementation_nativeSetDevicePixelRatio(JNI auto* impl = reinterpret_cast(instance); impl->set_device_pixel_ratio(ratio); } + +extern "C" JNIEXPORT void JNICALL +Java_org_serenityos_ladybird_WebViewImplementation_nativeMouseEvent(JNIEnv*, jobject /* thiz */, jlong instance, jint event_type, jfloat x, jfloat y, jfloat raw_x, jfloat raw_y) +{ + auto* impl = reinterpret_cast(instance); + + Web::MouseEvent::Type web_event_type; + + // These integers are defined in Android's MotionEvent. + // See https://developer.android.com/reference/android/view/MotionEvent#constants_1 + if (event_type == 0) { + // MotionEvent.ACTION_DOWN + web_event_type = Web::MouseEvent::Type::MouseDown; + } else if (event_type == 1) { + // MotionEvent.ACTION_UP + web_event_type = Web::MouseEvent::Type::MouseUp; + } else if (event_type == 2) { + // MotionEvent.ACTION_MOVE + web_event_type = Web::MouseEvent::Type::MouseMove; + } else { + // Unknown event type, default to MouseUp + web_event_type = Web::MouseEvent::Type::MouseUp; + } + + impl->mouse_event(web_event_type, x, y, raw_x, raw_y); +} diff --git a/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebView.kt b/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebView.kt index 343e92571ba..d1ed3a2698a 100644 --- a/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebView.kt +++ b/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebView.kt @@ -10,6 +10,7 @@ import android.content.Context import android.graphics.Bitmap import android.graphics.Canvas import android.util.AttributeSet +import android.view.MotionEvent import android.view.View // FIXME: This should (eventually) implement NestedScrollingChild3 and ScrollingView @@ -30,6 +31,23 @@ class WebView(context: Context, attributeSet: AttributeSet) : View(context, attr viewImpl.loadURL(url) } + override fun onTouchEvent(event: MotionEvent): Boolean { + // The native side only supports down, move, and up events. + // So, ignore any other MotionEvents. + if (event.action != MotionEvent.ACTION_DOWN && + event.action != MotionEvent.ACTION_MOVE && + event.action != MotionEvent.ACTION_UP) { + return super.onTouchEvent(event); + } + + // FIXME: We are passing these through as mouse events. + // We should really be handling them as touch events. + // (And we should handle scrolling - right now you have tap and drag the scrollbar!) + viewImpl.mouseEvent(event.action, event.x, event.y, event.rawX, event.rawY) + + return true + } + override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { super.onSizeChanged(w, h, oldw, oldh) contentBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888) diff --git a/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebViewImplementation.kt b/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebViewImplementation.kt index 49f214968a3..9de762dcbe6 100644 --- a/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebViewImplementation.kt +++ b/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebViewImplementation.kt @@ -11,6 +11,7 @@ import android.content.Intent import android.content.ServiceConnection import android.graphics.Bitmap import android.util.Log +import android.view.MotionEvent import android.view.View import java.net.URL @@ -49,6 +50,10 @@ class WebViewImplementation(private val view: WebView) { nativeSetDevicePixelRatio(nativeInstance, ratio) } + fun mouseEvent(eventType: Int, x: Float, y: Float, rawX: Float, rawY: Float) { + nativeMouseEvent(nativeInstance, eventType, x, y, rawX, rawY) + } + // Functions called from native code fun bindWebContentService(ipcFd: Int) { val connector = LadybirdServiceConnection(ipcFd, resourceDir) @@ -82,6 +87,7 @@ class WebViewImplementation(private val view: WebView) { private external fun nativeSetViewportGeometry(instance: Long, w: Int, h: Int) private external fun nativeSetDevicePixelRatio(instance: Long, ratio: Float) private external fun nativeLoadURL(instance: Long, url: String) + private external fun nativeMouseEvent(instance: Long, eventType: Int, x: Float, y: Float, rawX: Float, rawY: Float) companion object { /*