Bug 1757352 - Dispatch contextMenu event when right-clicking. r=geckoview-reviewers,m_kato,botond

Differential Revision: https://phabricator.services.mozilla.com/D200462
This commit is contained in:
jackyzy823 2024-03-23 07:24:24 +00:00
parent bda7caf6ed
commit 61f5a287e8
5 changed files with 224 additions and 2 deletions

View file

@ -37,6 +37,88 @@ class ContentDelegateChildTest : BaseSessionTest() {
mainSession.panZoomController.onTouchEvent(event)
}
private fun sendRightClickDown(x: Float, y: Float) {
val downTime = SystemClock.uptimeMillis()
var eventTime = SystemClock.uptimeMillis()
var pp = arrayOf(MotionEvent.PointerProperties())
pp[0].id = 0
pp[0].toolType = MotionEvent.TOOL_TYPE_MOUSE
var pc = arrayOf(MotionEvent.PointerCoords())
pc[0].x = x
pc[0].y = y
pc[0].pressure = 1.0f
pc[0].size = 1.0f
var event = MotionEvent.obtain(
downTime,
eventTime,
MotionEvent.ACTION_DOWN,
/* pointerCount */
1,
pp,
pc,
/* metaState */
0,
MotionEvent.BUTTON_SECONDARY,
/* xPrecision */
1.0f,
/* yPrecision */
1.0f,
/* deviceId */
0,
/* edgeFlags */
0,
InputDevice.SOURCE_MOUSE,
/* flags */
0,
)
mainSession.panZoomController.onTouchEvent(event)
}
private fun sendRightClickUp(x: Float, y: Float) {
val downTime = SystemClock.uptimeMillis()
var eventTime = SystemClock.uptimeMillis()
var pp = arrayOf(MotionEvent.PointerProperties())
pp[0].id = 0
pp[0].toolType = MotionEvent.TOOL_TYPE_MOUSE
var pc = arrayOf(MotionEvent.PointerCoords())
pc[0].x = x
pc[0].y = y
pc[0].pressure = 1.0f
pc[0].size = 1.0f
var event = MotionEvent.obtain(
downTime,
eventTime,
MotionEvent.ACTION_UP,
/* pointerCount */
1,
pp,
pc,
/* metaState */
0,
// buttonState is unset in ACTION_UP
/* buttonState */
0,
/* xPrecision */
1.0f,
/* yPrecision */
1.0f,
/* deviceId */
0,
/* edgeFlags */
0,
InputDevice.SOURCE_MOUSE,
/* flags */
0,
)
mainSession.panZoomController.onTouchEvent(event)
}
@WithDisplay(width = 100, height = 100)
@Test
fun requestContextMenuOnAudio() {
@ -276,6 +358,120 @@ class ContentDelegateChildTest : BaseSessionTest() {
})
}
@WithDisplay(width = 100, height = 100)
@Test
fun requestContextMenuOnLinkRightClickMouseUp() {
sessionRule.setPrefsUntilTestEnd(
mapOf(
"ui.context_menus.after_mouseup" to true,
),
)
mainSession.loadTestPath(CONTEXT_MENU_LINK_HTML_PATH)
mainSession.waitForPageStop()
sendRightClickDown(50f, 50f)
mainSession.delegateDuringNextWait(object : ContentDelegate {
@AssertCalled(false)
override fun onContextMenu(
session: GeckoSession,
screenX: Int,
screenY: Int,
element: ContextElement,
) {}
})
sendRightClickUp(50f, 50f)
mainSession.delegateUntilTestEnd(object : ContentDelegate {
@AssertCalled(count = 1)
override fun onContextMenu(
session: GeckoSession,
screenX: Int,
screenY: Int,
element: ContextElement,
) {
assertThat(
"Type should be none.",
element.type,
equalTo(ContextElement.TYPE_NONE),
)
assertThat(
"The element link title should be the title of the anchor.",
element.title,
equalTo("Hello Link Title"),
)
assertThat(
"The element link URI should be the href of the anchor.",
element.linkUri,
endsWith("hello.html"),
)
assertThat(
"The element link text content should be the text content of the anchor.",
element.textContent,
equalTo("Hello World"),
)
}
})
}
@WithDisplay(width = 100, height = 100)
@Test
fun requestContextMenuOnLinkRightClickMouseDown() {
sessionRule.setPrefsUntilTestEnd(
mapOf(
"ui.context_menus.after_mouseup" to false,
),
)
mainSession.loadTestPath(CONTEXT_MENU_LINK_HTML_PATH)
mainSession.waitForPageStop()
sendRightClickDown(50f, 50f)
mainSession.delegateDuringNextWait(object : ContentDelegate {
@AssertCalled(count = 1)
override fun onContextMenu(
session: GeckoSession,
screenX: Int,
screenY: Int,
element: ContextElement,
) {
assertThat(
"Type should be none.",
element.type,
equalTo(ContextElement.TYPE_NONE),
)
assertThat(
"The element link title should be the title of the anchor.",
element.title,
equalTo("Hello Link Title"),
)
assertThat(
"The element link URI should be the href of the anchor.",
element.linkUri,
endsWith("hello.html"),
)
assertThat(
"The element link text content should be the text content of the anchor.",
element.textContent,
equalTo("Hello World"),
)
}
})
sendRightClickUp(50f, 50f)
mainSession.delegateUntilTestEnd(object : ContentDelegate {
@AssertCalled(false)
override fun onContextMenu(
session: GeckoSession,
screenX: Int,
screenY: Int,
element: ContextElement,
) {}
})
}
@WithDisplay(width = 100, height = 100)
@Test
fun notRequestContextMenuWithPreventDefault() {

View file

@ -303,6 +303,9 @@ MouseInput::MouseInput(const WidgetMouseEventBase& aMouseEvent)
case eMouseHitTest:
mType = MOUSE_HITTEST;
break;
case eContextMenu:
mType = MOUSE_CONTEXTMENU;
break;
default:
MOZ_ASSERT_UNREACHABLE("Mouse event type not supported");
break;
@ -364,6 +367,9 @@ WidgetMouseEvent MouseInput::ToWidgetEvent(nsIWidget* aWidget) const {
case MOUSE_HITTEST:
msg = eMouseHitTest;
break;
case MOUSE_CONTEXTMENU:
msg = eContextMenu;
break;
default:
MOZ_ASSERT_UNREACHABLE(
"Did not assign a type to WidgetMouseEvent in MouseInput");

View file

@ -275,7 +275,8 @@ class MouseInput : public InputData {
MOUSE_WIDGET_ENTER,
MOUSE_WIDGET_EXIT,
MOUSE_HITTEST,
MOUSE_EXPLORE_BY_TOUCH
MOUSE_EXPLORE_BY_TOUCH,
MOUSE_CONTEXTMENU
));
MOZ_DEFINE_ENUM_AT_CLASS_SCOPE(

View file

@ -609,6 +609,22 @@ class NPZCSupport final
PostInputEvent([input = std::move(input), result](nsWindow* window) {
WidgetMouseEvent mouseEvent = input.ToWidgetEvent(window);
window->ProcessUntransformedAPZEvent(&mouseEvent, result);
if (MouseInput::SECONDARY_BUTTON == input.mButtonType) {
if ((StaticPrefs::ui_context_menus_after_mouseup() &&
MouseInput::MOUSE_UP == input.mType) ||
(!StaticPrefs::ui_context_menus_after_mouseup() &&
MouseInput::MOUSE_DOWN == input.mType)) {
MouseInput contextMenu = input;
// Actually we don't dispatch context menu event to APZ since we don't
// handle it on APZ yet. If handling it, we need to consider how to
// dispatch it on APZ thread. It may cause a race condition.
contextMenu.mType = MouseInput::MOUSE_CONTEXTMENU;
WidgetMouseEvent contextMenuEvent = contextMenu.ToWidgetEvent(window);
window->ProcessUntransformedAPZEvent(&contextMenuEvent, result);
}
}
});
switch (result.GetStatus()) {

View file

@ -36,7 +36,10 @@ skip-if = ["display == 'wayland'"] # Bug 1879835
support-files = "file_test_clipboard_getDataSnapshotSync.js"
["test_contextmenu_by_mouse_on_unix.html"]
run-if = ["os == 'linux'"]
run-if = [
"os == 'linux'",
"os == 'android'",
]
skip-if = ["headless"] # headless widget doesn't dispatch contextmenu event by mouse event.
["test_keypress_event_with_alt_on_mac.html"]