commit 4363c7054776a88cb81017ea928709ab9820ec06
parent 43609422072d75775412da5729121bd121106e5e
Author: Atila Butkovits <abutkovits@mozilla.com>
Date: Wed, 22 Oct 2025 18:23:42 +0300
Revert "Bug 1751335 - Adding right-click select on text in macOS r=masayuki" for causing bustages complaining about StaticPrefList.yaml.
This reverts commit 11f456595ac43091170bff03ee639757f0428667.
Diffstat:
5 files changed, 15 insertions(+), 420 deletions(-)
diff --git a/browser/actors/ContextMenuChild.sys.mjs b/browser/actors/ContextMenuChild.sys.mjs
@@ -662,45 +662,14 @@ export class ContextMenuChild extends JSWindowActorChild {
} catch (e) {}
}
- this._setContext(aEvent);
- let context = this.context;
- this.target = context.target;
-
- // If right-click select is enabled, we're on a link, and the link
- // text is not selected, select the link text.
- if (
- context.onLink &&
- Services.prefs.getBoolPref(
- "ui.mouse.right_click.select_under_cursor",
- false
- )
- ) {
- // Check if user-select: none is set on the link or its ancestors
- let shouldSelect = true;
- let elem = context.link;
- while (elem && shouldSelect) {
- if (this.contentWindow.getComputedStyle(elem).userSelect === "none") {
- shouldSelect = false;
- }
- elem = elem.parentElement;
- }
-
- if (shouldSelect) {
- const range = this.document.createRange();
- range.selectNodeContents(context.link);
- if (range.toString().trim().length) {
- const sel = this.contentWindow.getSelection();
- if (sel.isCollapsed || !sel.containsNode(context.link, true)) {
- sel.removeAllRanges();
- sel.addRange(range);
- }
- }
- }
- }
let selectionInfo = lazy.SelectionUtils.getSelectionDetails(
this.contentWindow
);
+ this._setContext(aEvent);
+ let context = this.context;
+ this.target = context.target;
+
let spellInfo = null;
let editFlags = null;
@@ -1249,6 +1218,7 @@ export class ContextMenuChild extends JSWindowActorChild {
context.onTelLink = context.linkProtocol == "tel";
context.onMozExtLink = context.linkProtocol == "moz-extension";
context.onSaveableLink = this._isLinkSaveable(context.link);
+
context.isSponsoredLink =
(elem.ownerDocument.URL === "about:newtab" ||
elem.ownerDocument.URL === "about:home") &&
diff --git a/browser/base/content/test/contextMenu/browser.toml b/browser/base/content/test/contextMenu/browser.toml
@@ -100,8 +100,6 @@ skip-if = ["os == 'linux' && socketprocess_networking"]
["browser_copy_link_to_highlight_viewsource.js"]
-["browser_right_click_select.js"]
-
["browser_save_image.js"]
["browser_strip_on_share_link.js"]
diff --git a/browser/base/content/test/contextMenu/browser_right_click_select.js b/browser/base/content/test/contextMenu/browser_right_click_select.js
@@ -1,309 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-const PREF_RIGHT_CLICK_SELECTS = "ui.mouse.right_click.select_under_cursor";
-const PREF_EDITABLE = "ui.mouse.right_click.select_in_editable";
-const PREF_EAT_SPACE = "layout.word_select.eat_space_to_next_word";
-
-const TEST_HTML = `<!doctype html>
-<title>Right-click selection</title>
-<style>
- #noselect { user-select: none; }
- .all { user-select: all; }
-</style>
- <p id="p1">Test Page <a id="link1" href="https://example.com">link text here</a> additional</p>
- <span id="plain">some plain selectable text</span>
- <div id="noselect">Unselectable box with <a id="nlink" href="https://example.com">link inside</a></div>
- <div class="all">user-select: all ancestor: <a id="alink" href="https://example.com">link text here</a></div>
- `;
-
-const EDITABLE_HTML = `<!doctype html>
-<title>Editable right-click</title>
-<div id="ed" contenteditable>hello world</div>
-`;
-const EDITABLE_PAGE = "data:text/html," + encodeURIComponent(EDITABLE_HTML);
-const TEST_PAGE = "data:text/html," + encodeURIComponent(TEST_HTML);
-
-// close context menu
-async function closeContextMenu(contextMenuEl) {
- const menuHidden = BrowserTestUtils.waitForEvent(
- contextMenuEl,
- "popuphidden"
- );
- contextMenuEl.hidePopup();
- await menuHidden;
-}
-
-// Right-click the center of a word
-async function openContextMenuOnWord(tabBrowser, elementSelector, targetWord) {
- const contextMenuEl = document.getElementById("contentAreaContextMenu");
- const menuShown = BrowserTestUtils.waitForEvent(contextMenuEl, "popupshown");
- await SpecialPowers.spawn(
- tabBrowser,
- [elementSelector, targetWord],
- (selector, word) => {
- const doc = content.document;
- const element = doc.querySelector(selector);
- const textNode = element.firstChild;
- const fullText = textNode.textContent;
- const startIndex = fullText.indexOf(word);
- const range = doc.createRange();
- range.setStart(textNode, startIndex);
- range.setEnd(textNode, startIndex + word.length);
- const wordRect = range.getBoundingClientRect();
- const x = wordRect.left + wordRect.width / 2;
- const y = wordRect.top + wordRect.height / 2;
- content.focus();
- content.windowUtils.sendMouseEvent("mousedown", x, y, 2, 1, 0);
- content.windowUtils.sendMouseEvent("contextmenu", x, y, 2, 1, 0);
- }
- );
- await menuShown;
- return contextMenuEl;
-}
-
-async function getSelectionText(tabBrowser) {
- return SpecialPowers.spawn(tabBrowser, [], () =>
- content.getSelection().toString()
- );
-}
-
-add_setup(async function () {
- await SpecialPowers.pushPrefEnv({
- set: [[PREF_EAT_SPACE, false]],
- });
-});
-
-add_task(async function right_click_plain_text_selects_clicked_word() {
- await SpecialPowers.pushPrefEnv({ set: [[PREF_RIGHT_CLICK_SELECTS, true]] });
- await BrowserTestUtils.withNewTab(TEST_PAGE, async tabBrowser => {
- const contextMenuEl = await openContextMenuOnWord(
- tabBrowser,
- "#plain",
- "plain"
- );
- const selection = await getSelectionText(tabBrowser);
- is(selection, "plain", "Right-click selected just the clicked word");
- const copy = contextMenuEl.querySelector("#context-copy");
- const copyLink = contextMenuEl.querySelector("#context-copylink");
- ok(BrowserTestUtils.isVisible(copy), "Copy is visible");
- ok(!copy.hasAttribute("disabled"), "Copy is enabled");
- ok(
- !BrowserTestUtils.isVisible(copyLink),
- "Copy Link is hidden on non-link text"
- );
- await closeContextMenu(contextMenuEl);
- });
-});
-
-add_task(async function user_select_none_container_does_not_auto_select() {
- await SpecialPowers.pushPrefEnv({ set: [[PREF_RIGHT_CLICK_SELECTS, true]] });
- await BrowserTestUtils.withNewTab(TEST_PAGE, async tabBrowser => {
- const contextMenuEl = await openContextMenuOnWord(
- tabBrowser,
- "#nlink",
- "link"
- );
- const selection = await getSelectionText(tabBrowser);
- is(selection, "", "No selection created in user-select:none region");
- const copyLink = contextMenuEl.querySelector("#context-copylink");
- ok(
- BrowserTestUtils.isVisible(copyLink),
- "Copy Link visible for link in noselect"
- );
- await closeContextMenu(contextMenuEl);
- });
-});
-
-add_task(async function right_click_link_text_shows_copy_and_copy_link() {
- await SpecialPowers.pushPrefEnv({ set: [[PREF_RIGHT_CLICK_SELECTS, true]] });
- await BrowserTestUtils.withNewTab(TEST_PAGE, async tabBrowser => {
- const contextMenuEl = await openContextMenuOnWord(
- tabBrowser,
- "#link1",
- "link"
- );
- const selection = await getSelectionText(tabBrowser);
- is(selection, "link text here", "Right-click selected whole link text");
- const copy = contextMenuEl.querySelector("#context-copy");
- const copyLink = contextMenuEl.querySelector("#context-copylink");
- ok(BrowserTestUtils.isVisible(copy), "Copy is visible");
- ok(!copy.hasAttribute("disabled"), "Copy is enabled");
- ok(
- BrowserTestUtils.isVisible(copyLink),
- "Copy Link is visible for link text"
- );
- await closeContextMenu(contextMenuEl);
- });
-});
-
-add_task(async function right_click_moves_selection_to_clicked_word() {
- await SpecialPowers.pushPrefEnv({ set: [[PREF_RIGHT_CLICK_SELECTS, true]] });
- await BrowserTestUtils.withNewTab(TEST_PAGE, async tabBrowser => {
- const contextMenuEl1 = await openContextMenuOnWord(
- tabBrowser,
- "#plain",
- "text"
- );
- await closeContextMenu(contextMenuEl1);
-
- const contextMenuEl2 = await openContextMenuOnWord(
- tabBrowser,
- "#plain",
- "plain"
- );
- const selection = await getSelectionText(tabBrowser);
- is(selection, "plain", "Selection moved to the clicked word");
- const copy = contextMenuEl2.querySelector("#context-copy");
- ok(BrowserTestUtils.isVisible(copy), "Copy visible");
- await closeContextMenu(contextMenuEl2);
- });
-});
-
-add_task(
- async function right_click_does_not_move_existing_selection_if_already_selected() {
- await SpecialPowers.pushPrefEnv({
- set: [[PREF_RIGHT_CLICK_SELECTS, true]],
- });
- await BrowserTestUtils.withNewTab(TEST_PAGE, async tabBrowser => {
- await SpecialPowers.spawn(tabBrowser, [], () => {
- const doc = content.document;
- const element = doc.getElementById("plain");
- const range = doc.createRange();
- range.selectNodeContents(element);
- const selection = content.getSelection();
- selection.removeAllRanges();
- selection.addRange(range);
- });
- const menu = await openContextMenuOnWord(tabBrowser, "#plain", "plain");
- const selection = await getSelectionText(tabBrowser);
- is(
- selection,
- "some plain selectable text",
- "Right-click does not move an existing selection if already selected"
- );
- const copy = menu.querySelector("#context-copy");
- ok(
- BrowserTestUtils.isVisible(copy),
- "Copy visible on existing selection"
- );
- await closeContextMenu(menu);
- });
- }
-);
-
-add_task(async function pref_off_does_not_select_plain_or_link() {
- await SpecialPowers.pushPrefEnv({ set: [[PREF_RIGHT_CLICK_SELECTS, false]] });
- await BrowserTestUtils.withNewTab(TEST_PAGE, async tabBrowser => {
- let menu = await openContextMenuOnWord(tabBrowser, "#plain", "plain");
- let sel = await getSelectionText(tabBrowser);
- is(sel, "", "pref=false: no selection on plain text");
- ok(
- !BrowserTestUtils.isVisible(menu.querySelector("#context-copy")),
- "pref=false: Copy hidden without selection on plain text"
- );
- await closeContextMenu(menu);
-
- menu = await openContextMenuOnWord(tabBrowser, "#link1", "link");
- sel = await getSelectionText(tabBrowser);
- is(sel, "", "pref=false: no selection on link text");
- ok(
- BrowserTestUtils.isVisible(menu.querySelector("#context-copylink")),
- "pref=false: Copy Link still visible on link"
- );
- await closeContextMenu(menu);
- });
-});
-
-add_task(async function user_select_all_ancestor_selects_ancestor_contents() {
- await SpecialPowers.pushPrefEnv({ set: [[PREF_RIGHT_CLICK_SELECTS, true]] });
- await BrowserTestUtils.withNewTab(TEST_PAGE, async tabBrowser => {
- const menu = await openContextMenuOnWord(tabBrowser, "#alink", "link");
- const sel = await getSelectionText(tabBrowser);
- is(
- sel,
- "link text here",
- "Select the nearest user-select:all ancestor's contents"
- );
- ok(
- BrowserTestUtils.isVisible(menu.querySelector("#context-copy")),
- "Copy visible with selection"
- );
- ok(
- BrowserTestUtils.isVisible(menu.querySelector("#context-copylink")),
- "Copy Link visible on link"
- );
- await closeContextMenu(menu);
- });
-});
-
-add_task(async function editable_pref_off_does_not_select_word() {
- await SpecialPowers.pushPrefEnv({
- set: [
- [PREF_RIGHT_CLICK_SELECTS, true],
- [PREF_EDITABLE, false],
- ],
- });
- await BrowserTestUtils.withNewTab(EDITABLE_PAGE, async tabBrowser => {
- const menu = await openContextMenuOnWord(tabBrowser, "#ed", "world");
- const sel = await getSelectionText(tabBrowser);
- is(sel, "", "pref=false: no text selection should be created in editable");
- await closeContextMenu(menu);
- });
-});
-
-add_task(async function editable_pref_on_selects_word() {
- await SpecialPowers.pushPrefEnv({
- set: [
- [PREF_RIGHT_CLICK_SELECTS, true],
- [PREF_EDITABLE, true],
- ],
- });
- await BrowserTestUtils.withNewTab(EDITABLE_PAGE, async tabBrowser => {
- const menu = await openContextMenuOnWord(tabBrowser, "#ed", "world");
- const sel = await getSelectionText(tabBrowser);
- is(
- sel,
- "world",
- "pref=true: right-click selects the clicked word in editable"
- );
- ok(
- BrowserTestUtils.isVisible(menu.querySelector("#context-copy")),
- "pref=true: Copy visible with a selection"
- );
- await closeContextMenu(menu);
- });
-});
-
-add_task(async function editable_existing_selection_is_preserved() {
- await SpecialPowers.pushPrefEnv({
- set: [
- [PREF_RIGHT_CLICK_SELECTS, true],
- [PREF_EDITABLE, true],
- ],
- });
- await BrowserTestUtils.withNewTab(EDITABLE_PAGE, async tabBrowser => {
- await SpecialPowers.spawn(tabBrowser, [], () => {
- const el = content.document.getElementById("ed").firstChild;
- const r = content.document.createRange();
- const txt = el.data;
- const start = txt.indexOf("hello");
- r.setStart(el, start);
- r.setEnd(el, start + "hello world".length);
- const sel = content.getSelection();
- sel.removeAllRanges();
- sel.addRange(r);
- });
-
- const menu = await openContextMenuOnWord(tabBrowser, "#ed", "hello");
- const sel = await getSelectionText(tabBrowser);
- is(
- sel,
- "hello world",
- "existing non-collapsed selection in editable is preserved"
- );
- await closeContextMenu(menu);
- });
-});
diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp
@@ -4962,64 +4962,16 @@ nsresult nsIFrame::MoveCaretToEventPoint(nsPresContext* aPresContext,
const bool isSecondaryButton =
aMouseEvent->mButton == MouseButton::eSecondary;
- if (isSecondaryButton) {
- const bool rightClickSelectIsEnabled =
- StaticPrefs::ui_mouse_right_click_select_under_cursor();
- const bool allowEditable =
- StaticPrefs::ui_mouse_right_click_select_in_editable();
- const bool isEditableHere =
- offsets.content && offsets.content->IsEditable();
- const bool selectClickedWord =
- rightClickSelectIsEnabled && (!isEditableHere || allowEditable);
- // On right-click, collapse the selection to the click point if enabled
- // in prefs, and either the target isn't editable or editable fields are
- // allowed.
-
- // sel is grabbed by hideSelectionChanges, so, it's safe to access this even
- // after running script.
- const OwningNonNull<Selection> sel = frameselection->NormalSelection();
- const SelectionBatcher hideSelectionChanges(
- *sel, __FUNCTION__, nsISelectionListener::MOUSEDOWN_REASON);
- const bool clickedOnCaret =
- sel->IsCollapsed() && sel->GetAnchorNode() == offsets.content &&
- sel->AnchorOffset() == static_cast<uint32_t>(offsets.StartOffset());
- if (offsets.content && offsets.offset >= 0 && selectClickedWord &&
- !nsContentUtils::IsPointInSelection(
- *sel, *offsets.content, static_cast<uint32_t>(offsets.offset),
- true)) {
- // Collapse selection to the clicked point.
- nsCOMPtr<nsIContent> content = offsets.content;
- fc->HandleClick(content, offsets.StartOffset(), offsets.EndOffset(),
- nsFrameSelection::FocusMode::kCollapseToNewPoint,
- offsets.associate);
- }
-
- if (!MovingCaretToEventPointAllowedIfSecondaryButtonEvent(
- *frameselection, *aMouseEvent, *offsets.content,
- // When we collapse selection in nsFrameSelection::TakeFocus,
- // we always collapse selection to the start offset. Therefore,
- // we can ignore the end offset here. E.g., when an <img> is
- // clicked, set the primary offset to after it, but the the
- // secondary offset may be before it, see OffsetsForSingleFrame for
- // the detail.
- offsets.StartOffset())) {
- return NS_OK;
- }
-
- if (selectClickedWord) {
- // Skip word selection when right-clicking directly on the caret in an
- // editable field. Users typically right-click here to open the context
- // menu, not to select text.
- if (isEditableHere && clickedOnCaret) {
- return NS_OK;
- }
- nsIFrame* frameUnderPoint =
- nsLayoutUtils::GetFrameForPoint(RelativeTo{this}, pt);
- if (!frameUnderPoint->IsTextFrame()) {
- return NS_OK;
- }
- return SelectByTypeAtPoint(pt, eSelectWord, eSelectWord, 0);
- }
+ if (isSecondaryButton &&
+ !MovingCaretToEventPointAllowedIfSecondaryButtonEvent(
+ *frameselection, *aMouseEvent, *offsets.content,
+ // When we collapse selection in nsFrameSelection::TakeFocus,
+ // we always collapse selection to the start offset. Therefore,
+ // we can ignore the end offset here. E.g., when an <img> is clicked,
+ // set the primary offset to after it, but the the secondary offset
+ // may be before it, see OffsetsForSingleFrame for the detail.
+ offsets.StartOffset())) {
+ return NS_OK;
}
if (aMouseEvent->mMessage == eMouseDown &&
diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml
@@ -18305,22 +18305,6 @@
value: false
mirror: always
-# When true, right-clicking selects the word/link under the cursor.
-- name: ui.mouse.right_click.select_under_cursor
- type: bool
-#ifdef XP_MACOSX
- value: @EARLY_BETA_OR_EARLIER@
-#else
- value: false
-#endif
- mirror: always
-
-# When true, right-clicking selects the word under the cursor in editable
-- name: ui.mouse.right_click.select_in_editable
- type: bool
- value: false
- mirror: always
-
#---------------------------------------------------------------------------
# Prefs starting with "urlclassifier."
#---------------------------------------------------------------------------