From 7b5eb1f46ee75083326408f3dc1e1cb6a67d865f Mon Sep 17 00:00:00 2001 From: TW Date: Mon, 13 Jul 2026 21:19:26 +0800 Subject: [PATCH 1/2] fix: keep result panel interactions working across iframes - Cover page content with a transparent shield while the result panel is dragged or resized. - Forward child-frame mouse input so unpinned panels keep click-away behavior. - Add regression coverage for shield activation, frame routing, and extension controls. --- .../src/background/background.js | 3 +- .../src/background/library/frame_events.js | 27 +++++ .../src/common/scripts/frame_events.js | 2 + .../display/library/moveable/resizable.js | 1 + .../src/content/display/panel/PanelView.jsx | 2 + .../display/panel/panel_drag_shield.js | 21 ++++ .../content/display/panel/panel_handlers.js | 11 ++ .../content/display/panel/panel_runtime.js | 9 +- .../src/content/display/panel/panel_styles.js | 13 +++ .../display/panel/use_result_panel_model.js | 10 +- .../content/select/frame_pointer_bridge.js | 27 +++++ .../src/content/select/select.js | 2 + .../test/unit/background/frame_events.test.js | 27 +++++ .../content/display/panel_handlers.test.js | 20 ++++ .../content/display/panel_runtime.test.js | 107 ++++++++++++++++++ .../select/frame_pointer_bridge.test.js | 37 ++++++ 16 files changed, 316 insertions(+), 3 deletions(-) create mode 100644 packages/EdgeTranslate/src/background/library/frame_events.js create mode 100644 packages/EdgeTranslate/src/common/scripts/frame_events.js create mode 100644 packages/EdgeTranslate/src/content/display/panel/panel_drag_shield.js create mode 100644 packages/EdgeTranslate/src/content/select/frame_pointer_bridge.js create mode 100644 packages/EdgeTranslate/test/unit/background/frame_events.test.js create mode 100644 packages/EdgeTranslate/test/unit/content/select/frame_pointer_bridge.test.js diff --git a/packages/EdgeTranslate/src/background/background.js b/packages/EdgeTranslate/src/background/background.js index 2463dd5c..7665255e 100644 --- a/packages/EdgeTranslate/src/background/background.js +++ b/packages/EdgeTranslate/src/background/background.js @@ -17,6 +17,7 @@ import { setDefaultSettings, } from "common/scripts/settings.js"; import { resolveContextMenuSelection } from "./library/context_menu.js"; +import { registerSubframePointerDownForwarder } from "./library/frame_events.js"; import "./library/pdf_file_access.js"; if (typeof BUILD_ENV !== "undefined" && BUILD_ENV === "development") { @@ -183,7 +184,7 @@ function showUpdateNotification() { /** * Create communication channel. */ -const channel = new Channel(); +const channel = registerSubframePointerDownForwarder(new Channel()); /** * Create translator manager and register event listeners and service providers. diff --git a/packages/EdgeTranslate/src/background/library/frame_events.js b/packages/EdgeTranslate/src/background/library/frame_events.js new file mode 100644 index 00000000..7de39b9e --- /dev/null +++ b/packages/EdgeTranslate/src/background/library/frame_events.js @@ -0,0 +1,27 @@ +import { + SUBFRAME_POINTER_DOWN_EVENT, + TOP_FRAME_POINTER_DOWN_EVENT, +} from "common/scripts/frame_events.js"; + +export function registerSubframePointerDownForwarder(channel) { + channel.on(SUBFRAME_POINTER_DOWN_EVENT, (_detail, sender) => { + forwardSubframePointerDown(sender); + }); + return channel; +} + +export function forwardSubframePointerDown(sender) { + const tabId = sender.tab?.id; + if (!Number.isInteger(tabId) || !Number.isInteger(sender.frameId) || sender.frameId <= 0) { + return false; + } + + const message = JSON.stringify({ + type: "event", + event: TOP_FRAME_POINTER_DOWN_EVENT, + }); + chrome.tabs.sendMessage(tabId, message, { frameId: 0 }, () => { + void chrome.runtime.lastError; + }); + return true; +} diff --git a/packages/EdgeTranslate/src/common/scripts/frame_events.js b/packages/EdgeTranslate/src/common/scripts/frame_events.js new file mode 100644 index 00000000..5aed5d63 --- /dev/null +++ b/packages/EdgeTranslate/src/common/scripts/frame_events.js @@ -0,0 +1,2 @@ +export const SUBFRAME_POINTER_DOWN_EVENT = "subframe_pointer_down"; +export const TOP_FRAME_POINTER_DOWN_EVENT = "top_frame_pointer_down"; diff --git a/packages/EdgeTranslate/src/content/display/library/moveable/resizable.js b/packages/EdgeTranslate/src/content/display/library/moveable/resizable.js index aba324d7..1a25bb46 100644 --- a/packages/EdgeTranslate/src/content/display/library/moveable/resizable.js +++ b/packages/EdgeTranslate/src/content/display/library/moveable/resizable.js @@ -177,6 +177,7 @@ export default class resizable { /* call the drag start handler written by the user */ this.handlers.resizeStart && this.handlers.resizeStart({ + inputEvent: e, // set the start position set: (position) => { this.store.startTranslate = [position[0], position[1]]; // deep copy diff --git a/packages/EdgeTranslate/src/content/display/panel/PanelView.jsx b/packages/EdgeTranslate/src/content/display/panel/PanelView.jsx index 819ca533..d136800f 100644 --- a/packages/EdgeTranslate/src/content/display/panel/PanelView.jsx +++ b/packages/EdgeTranslate/src/content/display/panel/PanelView.jsx @@ -13,6 +13,7 @@ import CloseIcon from "../icons/close.svg"; import { MaxZIndex, GlobalStyle, + DragShield, Panel, Head, HeadIcons, @@ -39,6 +40,7 @@ export default function PanelView(props) { +