fix(design): a right-click on selected words opens the browser's own menu (E28 S3e4b)
The row menu took every right-click, so selected text could only be copied with Ctrl+C. On the selection (its laid-out line boxes) the event is left to the browser; beside it the object's menu opens as before.
This commit is contained in:
@@ -29,3 +29,24 @@ export function movedPastSlop(
|
||||
if (!from || e.detail === 0) return false;
|
||||
return Math.abs(e.clientX - from.x) > CLICK_SLOP || Math.abs(e.clientY - from.y) > CLICK_SLOP;
|
||||
}
|
||||
|
||||
// The copy half: a right-click on selected words is a request for the browser's own menu (Copy,
|
||||
// Search, Translate), not the object's. An app menu there would leave Ctrl+C as the only way to copy
|
||||
// what the reader just selected. Only ON the selection: a right-click beside it (the row's picture,
|
||||
// its padding) still means the object.
|
||||
|
||||
/** True when the page's selection is non-empty and the point (x, y) over `target` lies on it. Where
|
||||
* the engine lays out ranges (a browser), "on it" is inside one of the selection's line boxes; where
|
||||
* it does not (jsdom), it is `target` touching the selection. */
|
||||
export function pointOnSelection(target: EventTarget | null, x: number, y: number): boolean {
|
||||
const sel = typeof window === "undefined" ? null : window.getSelection();
|
||||
if (!sel || sel.isCollapsed || !sel.toString().trim() || !(target instanceof Node)) return false;
|
||||
for (let i = 0; i < sel.rangeCount; i++) {
|
||||
const range = sel.getRangeAt(i);
|
||||
if (!range.intersectsNode(target)) continue;
|
||||
if (typeof range.getClientRects !== "function") return true;
|
||||
for (const r of range.getClientRects())
|
||||
if (x >= r.left && x <= r.right && y >= r.top && y <= r.bottom) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user