From ece9908070ede0f52738b91b705856f8753d53b5 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Wed, 13 Sep 2023 20:07:01 -0400 Subject: [PATCH] Ladybird: Add context menu items to the AppKit chrome to inspect nodes --- Ladybird/AppKit/UI/Inspector.h | 1 + Ladybird/AppKit/UI/Inspector.mm | 53 +++++++++++++++++++++++++++ Ladybird/AppKit/UI/LadybirdWebView.mm | 23 ++++++++++++ Ladybird/AppKit/UI/Tab.mm | 8 ++++ 4 files changed, 85 insertions(+) diff --git a/Ladybird/AppKit/UI/Inspector.h b/Ladybird/AppKit/UI/Inspector.h index 5cca8b5862..68aa0d42b7 100644 --- a/Ladybird/AppKit/UI/Inspector.h +++ b/Ladybird/AppKit/UI/Inspector.h @@ -16,6 +16,7 @@ - (instancetype)init:(Tab*)tab; - (void)inspect; +- (void)inspectHoveredElement; - (void)reset; @end diff --git a/Ladybird/AppKit/UI/Inspector.mm b/Ladybird/AppKit/UI/Inspector.mm index b956a6f0e3..b0989dbdb1 100644 --- a/Ladybird/AppKit/UI/Inspector.mm +++ b/Ladybird/AppKit/UI/Inspector.mm @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -43,7 +44,10 @@ struct Selection { @interface Inspector () { + BOOL m_dom_tree_loaded; + Selection m_selection; + Optional m_pending_selection; HashMap m_dom_node_to_parent_map; HashMap 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) diff --git a/Ladybird/AppKit/UI/LadybirdWebView.mm b/Ladybird/AppKit/UI/LadybirdWebView.mm index bba79d03e4..6640ffd73c 100644 --- a/Ladybird/AppKit/UI/LadybirdWebView.mm +++ b/Ladybird/AppKit/UI/LadybirdWebView.mm @@ -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; diff --git a/Ladybird/AppKit/UI/Tab.mm b/Ladybird/AppKit/UI/Tab.mm index 61fabf617c..8dd947995f 100644 --- a/Ladybird/AppKit/UI/Tab.mm +++ b/Ladybird/AppKit/UI/Tab.mm @@ -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