devtools: Allow highlighting elements from the inspector (#35822)

This change connects the `HighlighterActor` from the devtools with the
document, which will draw a blue rectangle over any highlighted dom
node.



https://github.com/user-attachments/assets/571b2dab-497f-4102-9e55-517cdcc040ba




---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by
`[X]` when the step is complete, and replace `___` with appropriate
data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes do not require tests because we don't have devtools
tests

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
Simon Wülker 2025-05-05 12:10:25 +02:00 committed by GitHub
parent 20f20a07f2
commit 8608e328a1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 305 additions and 4 deletions

View file

@ -538,3 +538,21 @@ pub(crate) fn handle_get_css_database(reply: IpcSender<HashMap<String, CssDataba
.collect();
let _ = reply.send(database);
}
pub(crate) fn handle_highlight_dom_node(
documents: &DocumentCollection,
id: PipelineId,
node_id: Option<String>,
) {
let node = node_id.and_then(|node_id| {
let node = find_node_by_unique_id(documents, id, &node_id);
if node.is_none() {
log::warn!("Node id {node_id} for pipeline id {id} is not found",);
}
node
});
if let Some(window) = documents.find_window(id) {
window.Document().highlight_dom_node(node.as_deref());
}
}

View file

@ -565,6 +565,8 @@ pub(crate) struct Document {
/// The active keyboard modifiers for the WebView. This is updated when receiving any input event.
#[no_trace]
active_keyboard_modifiers: Cell<Modifiers>,
/// The node that is currently highlighted by the devtools
highlighted_dom_node: MutNullableDom<Node>,
}
#[allow(non_snake_case)]
@ -4222,6 +4224,7 @@ impl Document {
intersection_observer_task_queued: Cell::new(false),
intersection_observers: Default::default(),
active_keyboard_modifiers: Cell::new(Modifiers::empty()),
highlighted_dom_node: Default::default(),
}
}
@ -5213,6 +5216,14 @@ impl Document {
self.has_trustworthy_ancestor_origin.get() ||
self.origin().immutable().is_potentially_trustworthy()
}
pub(crate) fn highlight_dom_node(&self, node: Option<&Node>) {
self.highlighted_dom_node.set(node);
self.set_needs_paint(true);
}
pub(crate) fn highlighted_dom_node(&self) -> Option<DomRoot<Node>> {
self.highlighted_dom_node.get()
}
}
#[allow(non_snake_case)]

View file

@ -2142,6 +2142,8 @@ impl Window {
.or_else(|| document.GetDocumentElement())
.map(|root| root.upcast::<Node>().to_trusted_node_address());
let highlighted_dom_node = document.highlighted_dom_node().map(|node| node.to_opaque());
// Send new document and relevant styles to layout.
let reflow = ReflowRequest {
reflow_info: Reflow {
@ -2161,6 +2163,7 @@ impl Window {
.image_animation_manager_mut()
.take_image_animate_set(),
theme: self.theme.get(),
highlighted_dom_node,
};
let Some(results) = self.layout.borrow_mut().reflow(reflow) else {

View file

@ -2069,6 +2069,9 @@ impl ScriptThread {
None => warn!("Message sent to closed pipeline {}.", id),
}
},
DevtoolScriptControlMsg::HighlightDomNode(id, node_id) => {
devtools::handle_highlight_dom_node(&documents, id, node_id)
},
}
}