diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 6c76d3a2197f..7fffbc6bdce2 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -6251,6 +6251,7 @@ public class com/facebook/react/views/textinput/ReactEditText : androidx/appcomp public final fun maybeUpdateTypeface ()V public fun onAttachedToWindow ()V public fun onConfigurationChanged (Landroid/content/res/Configuration;)V + protected fun onCreateContextMenu (Landroid/view/ContextMenu;)V public fun onCreateInputConnection (Landroid/view/inputmethod/EditorInfo;)Landroid/view/inputmethod/InputConnection; public fun onDragEvent (Landroid/view/DragEvent;)Z public fun onDraw (Landroid/graphics/Canvas;)V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.kt index 754f10026624..aa09eea8811a 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.kt @@ -29,6 +29,7 @@ import android.text.method.KeyListener import android.text.method.QwertyKeyListener import android.util.TypedValue import android.view.ActionMode +import android.view.ContextMenu import android.view.DragEvent import android.view.Gravity import android.view.KeyEvent @@ -388,6 +389,16 @@ public open class ReactEditText public constructor(context: Context) : AppCompat if (id == android.R.id.paste) android.R.id.pasteAsPlainText else id, ) + /* + * A secondary click opens the context menu that Editor fills with the text actions. With + * contextMenuHidden it gets no items, so no menu opens. + */ + override fun onCreateContextMenu(menu: ContextMenu) { + if (!contextMenuHidden) { + super.onCreateContextMenu(menu) + } + } + internal fun clearFocusAndMaybeRefocus() { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P || !isInTouchMode) { super.clearFocus() diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/views/textinput/ReactTextInputPropertyTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/views/textinput/ReactTextInputPropertyTest.kt index 82ec014eb89e..71553665f5e4 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/views/textinput/ReactTextInputPropertyTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/views/textinput/ReactTextInputPropertyTest.kt @@ -11,8 +11,10 @@ package com.facebook.react.views.textinput +import android.app.Activity import android.graphics.Color import android.os.Build +import android.os.Looper import android.text.InputFilter import android.text.InputFilter.AllCaps import android.text.InputType @@ -46,8 +48,10 @@ import org.assertj.core.api.Assertions.assertThat import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.robolectric.Robolectric import org.robolectric.RobolectricTestRunner import org.robolectric.RuntimeEnvironment +import org.robolectric.Shadows.shadowOf /** Verify {@link EditText} view property being applied properly by {@link ReactTextInputManager} */ @RunWith(RobolectricTestRunner::class) @@ -652,6 +656,22 @@ class ReactTextInputPropertyTest { .isNull() } + @Test + fun testContextMenuHiddenRightClick() { + val activity = Robolectric.buildActivity(Activity::class.java).setup().get() + activity.setContentView(view) + view.setText("text") + shadowOf(Looper.getMainLooper()).idle() + + // A mouse right-click opens the context menu at the pointer through showContextMenu(x, y), + // which answers whether a menu opened. + manager.updateProperties(view, buildStyles()) + assertThat(view.showContextMenu(1f, 1f)).isTrue + + manager.updateProperties(view, buildStyles("contextMenuHidden", true)) + assertThat(view.showContextMenu(1f, 1f)).isFalse + } + private fun buildStyles(vararg keysAndValues: Any?): ReactStylesDiffMap { return ReactStylesDiffMap(JavaOnlyMap.of(*keysAndValues)) }