forked from mirrors/gecko-dev
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:
parent
bda7caf6ed
commit
61f5a287e8
5 changed files with 224 additions and 2 deletions
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
|
|
|
|||
Loading…
Reference in a new issue