1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 15:47:44 +00:00

Ladybird: Add context menu items to the AppKit chrome to inspect nodes

This commit is contained in:
Timothy Flynn 2023-09-13 20:07:01 -04:00 committed by Andrew Kaster
parent bd1e35c726
commit ece9908070
4 changed files with 85 additions and 0 deletions

View file

@ -16,6 +16,7 @@
- (instancetype)init:(Tab*)tab;
- (void)inspect;
- (void)inspectHoveredElement;
- (void)reset;
@end

View file

@ -6,6 +6,7 @@
#include <AK/DeprecatedString.h>
#include <AK/HashMap.h>
#include <AK/Optional.h>
#include <AK/Traits.h>
#include <LibWeb/CSS/Selector.h>
#include <LibWebView/ViewImplementation.h>
@ -43,7 +44,10 @@ struct Selection {
@interface Inspector () <NSOutlineViewDataSource, NSOutlineViewDelegate, NSTableViewDataSource>
{
BOOL m_dom_tree_loaded;
Selection m_selection;
Optional<i32> m_pending_selection;
HashMap<NSDictionary*, NSDictionary*> m_dom_node_to_parent_map;
HashMap<i32, NSDictionary*> m_node_id_to_dom_node_map;
@ -118,6 +122,11 @@ struct Selection {
[strong_self.dom_tree_outline_view sizeToFit];
[strong_self prepareDOMNodeMaps:strong_self.dom_tree parentNode:nil];
strong_self->m_dom_tree_loaded = YES;
if (strong_self->m_pending_selection.has_value()) {
[strong_self inspectDOMNodeID:strong_self->m_pending_selection.release_value()];
}
} else {
strong_self.dom_tree = @{};
}
@ -149,9 +158,25 @@ struct Selection {
web_view.inspect_dom_tree();
}
- (void)inspectHoveredElement
{
auto& web_view = [[self.tab web_view] view];
auto node_id = web_view.get_hovered_node_id();
if (!m_dom_tree_loaded) {
m_pending_selection = node_id;
return;
}
[self inspectDOMNodeID:node_id];
}
- (void)reset
{
m_dom_tree_loaded = NO;
m_selection = {};
m_pending_selection = {};
m_dom_node_to_parent_map = {};
m_node_id_to_dom_node_map = {};
@ -261,6 +286,34 @@ struct Selection {
}
}
- (void)inspectDOMNodeID:(i32)node_id
{
auto dom_node = m_node_id_to_dom_node_map.get(node_id);
if (!dom_node.has_value()) {
return;
}
[self expandDOMNode:*dom_node];
if (auto row = [self.dom_tree_outline_view rowForItem:*dom_node]; row != -1) {
auto index = [NSIndexSet indexSetWithIndex:row];
[self.dom_tree_outline_view selectRowIndexes:index byExtendingSelection:NO];
}
[self setSelection: { node_id }];
}
- (void)expandDOMNode:(NSDictionary*)dom_node
{
// We can't expand an item unless its parent is also already expanded, so walk up the tree to
// expand all ancestors.
if (auto parent_node = m_dom_node_to_parent_map.get(dom_node); parent_node.has_value()) {
[self expandDOMNode:*parent_node];
}
[self.dom_tree_outline_view expandItem:dom_node];
}
- (void)setSelection:(Selection)selection
{
if (selection == m_selection)

View file

@ -722,6 +722,9 @@ static void copy_text_to_clipboard(StringView text)
[_page_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"View Source"
action:@selector(viewSource:)
keyEquivalent:@""]];
[_page_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Inspect Element"
action:@selector(inspectElement:)
keyEquivalent:@""]];
}
return _page_context_menu;
@ -743,6 +746,11 @@ static void copy_text_to_clipboard(StringView text)
[_link_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Copy URL"
action:@selector(copyLink:)
keyEquivalent:@""]];
[_link_context_menu addItem:[NSMenuItem separatorItem]];
[_link_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Inspect Element"
action:@selector(inspectElement:)
keyEquivalent:@""]];
}
return _link_context_menu;
@ -767,6 +775,11 @@ static void copy_text_to_clipboard(StringView text)
[_image_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Copy Image URL"
action:@selector(copyLink:)
keyEquivalent:@""]];
[_image_context_menu addItem:[NSMenuItem separatorItem]];
[_image_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Inspect Element"
action:@selector(inspectElement:)
keyEquivalent:@""]];
}
return _image_context_menu;
@ -814,6 +827,11 @@ static void copy_text_to_clipboard(StringView text)
[_audio_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Copy Audio URL"
action:@selector(copyLink:)
keyEquivalent:@""]];
[_audio_context_menu addItem:[NSMenuItem separatorItem]];
[_audio_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Inspect Element"
action:@selector(inspectElement:)
keyEquivalent:@""]];
}
return _audio_context_menu;
@ -861,6 +879,11 @@ static void copy_text_to_clipboard(StringView text)
[_video_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Copy Video URL"
action:@selector(copyLink:)
keyEquivalent:@""]];
[_video_context_menu addItem:[NSMenuItem separatorItem]];
[_video_context_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Inspect Element"
action:@selector(inspectElement:)
keyEquivalent:@""]];
}
return _video_context_menu;

View file

@ -149,6 +149,14 @@ static constexpr CGFloat const WINDOW_HEIGHT = 800;
self.inspector_controller = nil;
}
- (void)inspectElement:(id)sender
{
[self openInspector:sender];
auto* inspector = (Inspector*)[self.inspector_controller window];
[inspector inspectHoveredElement];
}
#pragma mark - Private methods
- (TabController*)tabController