mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-11 17:00:37 +00:00
UI/AppKit: Implement opening child web views from e.g. window.open
Some checks are pending
CI / Lagom (true, NO_FUZZ, ubuntu-22.04, Linux, Clang) (push) Waiting to run
CI / Lagom (false, FUZZ, ubuntu-22.04, Linux, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, macos-14, macOS, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, ubuntu-22.04, Linux, GNU) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (macos-14, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (ubuntu-22.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Push notes / build (push) Waiting to run
Some checks are pending
CI / Lagom (true, NO_FUZZ, ubuntu-22.04, Linux, Clang) (push) Waiting to run
CI / Lagom (false, FUZZ, ubuntu-22.04, Linux, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, macos-14, macOS, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, ubuntu-22.04, Linux, GNU) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (macos-14, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (ubuntu-22.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Push notes / build (push) Waiting to run
This has been implemented in Qt for quite some time. This patch adds the same feature to AppKit. This is needed to run many WPT subtests with the AppKit chrome. This is also needed to handle window.open, target=_blank link clicks, etc.
This commit is contained in:
parent
e6965b11e4
commit
27776c8854
Notes:
github-actions[bot]
2024-09-18 08:11:03 +00:00
Author: https://github.com/trflynn89 Commit: https://github.com/LadybirdBrowser/ladybird/commit/27776c88541 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1422
10 changed files with 154 additions and 12 deletions
|
@ -13,6 +13,7 @@
|
|||
#include <LibWeb/CSS/PreferredContrast.h>
|
||||
#include <LibWeb/CSS/PreferredMotion.h>
|
||||
#include <LibWeb/HTML/ActivateTab.h>
|
||||
#include <LibWebView/Forward.h>
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
|
@ -32,6 +33,11 @@
|
|||
fromTab:(nullable Tab*)tab
|
||||
activateTab:(Web::HTML::ActivateTab)activate_tab;
|
||||
|
||||
- (nonnull TabController*)createChildTab:(Optional<URL::URL> const&)url
|
||||
fromTab:(nonnull Tab*)tab
|
||||
activateTab:(Web::HTML::ActivateTab)activate_tab
|
||||
pageIndex:(u64)page_index;
|
||||
|
||||
- (void)setActiveTab:(nonnull Tab*)tab;
|
||||
- (nullable Tab*)activeTab;
|
||||
|
||||
|
|
|
@ -116,6 +116,20 @@
|
|||
return controller;
|
||||
}
|
||||
|
||||
- (nonnull TabController*)createChildTab:(Optional<URL::URL> const&)url
|
||||
fromTab:(nonnull Tab*)tab
|
||||
activateTab:(Web::HTML::ActivateTab)activate_tab
|
||||
pageIndex:(u64)page_index
|
||||
{
|
||||
auto* controller = [self createChildTab:activate_tab fromTab:tab pageIndex:page_index];
|
||||
|
||||
if (url.has_value()) {
|
||||
[controller loadURL:*url];
|
||||
}
|
||||
|
||||
return controller;
|
||||
}
|
||||
|
||||
- (void)setActiveTab:(Tab*)tab
|
||||
{
|
||||
self.active_tab = tab;
|
||||
|
@ -175,6 +189,29 @@
|
|||
fromTab:(nullable Tab*)tab
|
||||
{
|
||||
auto* controller = [[TabController alloc] init];
|
||||
[self initializeTabController:controller
|
||||
activateTab:activate_tab
|
||||
fromTab:tab];
|
||||
|
||||
return controller;
|
||||
}
|
||||
|
||||
- (nonnull TabController*)createChildTab:(Web::HTML::ActivateTab)activate_tab
|
||||
fromTab:(nonnull Tab*)tab
|
||||
pageIndex:(u64)page_index
|
||||
{
|
||||
auto* controller = [[TabController alloc] initAsChild:tab pageIndex:page_index];
|
||||
[self initializeTabController:controller
|
||||
activateTab:activate_tab
|
||||
fromTab:tab];
|
||||
|
||||
return controller;
|
||||
}
|
||||
|
||||
- (void)initializeTabController:(TabController*)controller
|
||||
activateTab:(Web::HTML::ActivateTab)activate_tab
|
||||
fromTab:(nullable Tab*)tab
|
||||
{
|
||||
[controller showWindow:nil];
|
||||
|
||||
if (tab) {
|
||||
|
@ -192,7 +229,6 @@
|
|||
|
||||
[self.managed_tabs addObject:controller];
|
||||
[controller onCreateNewTab];
|
||||
return controller;
|
||||
}
|
||||
|
||||
- (void)closeCurrentTab:(id)sender
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
url:(URL::URL const&)url
|
||||
activateTab:(Web::HTML::ActivateTab)activate_tab;
|
||||
|
||||
- (String const&)onCreateChildTab:(Optional<URL::URL> const&)url
|
||||
activateTab:(Web::HTML::ActivateTab)activate_tab
|
||||
pageIndex:(u64)page_index;
|
||||
|
||||
- (void)loadURL:(URL::URL const&)url;
|
||||
- (void)onLoadStart:(URL::URL const&)url isRedirect:(BOOL)is_redirect;
|
||||
- (void)onLoadFinish:(URL::URL const&)url;
|
||||
|
@ -47,6 +51,9 @@
|
|||
@interface LadybirdWebView : NSClipView <NSMenuDelegate>
|
||||
|
||||
- (instancetype)init:(id<LadybirdWebViewObserver>)observer;
|
||||
- (instancetype)initAsChild:(id<LadybirdWebViewObserver>)observer
|
||||
parent:(LadybirdWebView*)parent
|
||||
pageIndex:(u64)page_index;
|
||||
|
||||
- (void)loadURL:(URL::URL const&)url;
|
||||
- (void)loadHTML:(StringView)html;
|
||||
|
|
|
@ -88,6 +88,26 @@ struct HideCursor {
|
|||
@synthesize status_label = _status_label;
|
||||
|
||||
- (instancetype)init:(id<LadybirdWebViewObserver>)observer
|
||||
{
|
||||
if (self = [self initWebView:observer]) {
|
||||
m_web_view_bridge->initialize_client();
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initAsChild:(id<LadybirdWebViewObserver>)observer
|
||||
parent:(LadybirdWebView*)parent
|
||||
pageIndex:(u64)page_index
|
||||
{
|
||||
if (self = [self initWebView:observer]) {
|
||||
m_web_view_bridge->initialize_client_as_child(*parent->m_web_view_bridge, page_index);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWebView:(id<LadybirdWebViewObserver>)observer
|
||||
{
|
||||
if (self = [super init]) {
|
||||
self.observer = observer;
|
||||
|
@ -109,8 +129,6 @@ struct HideCursor {
|
|||
m_web_view_bridge = MUST(Ladybird::WebViewBridge::create(move(screen_rects), device_pixel_ratio, [delegate preferredColorScheme], [delegate preferredContrast], [delegate preferredMotion]));
|
||||
[self setWebViewCallbacks];
|
||||
|
||||
m_web_view_bridge->initialize_client();
|
||||
|
||||
auto* area = [[NSTrackingArea alloc] initWithRect:[self bounds]
|
||||
options:NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect | NSTrackingMouseMoved
|
||||
owner:self
|
||||
|
@ -317,12 +335,18 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_
|
|||
[self setNeedsDisplay:YES];
|
||||
};
|
||||
|
||||
m_web_view_bridge->on_new_web_view = [weak_self](auto activate_tab, auto, auto) {
|
||||
m_web_view_bridge->on_new_web_view = [weak_self](auto activate_tab, auto, auto page_index) {
|
||||
LadybirdWebView* self = weak_self;
|
||||
if (self == nil) {
|
||||
return String {};
|
||||
}
|
||||
// FIXME: Create a child tab that re-uses the ConnectionFromClient of the parent tab
|
||||
|
||||
if (page_index.has_value()) {
|
||||
return [self.observer onCreateChildTab:{}
|
||||
activateTab:activate_tab
|
||||
pageIndex:*page_index];
|
||||
}
|
||||
|
||||
return [self.observer onCreateNewTab:{} activateTab:activate_tab];
|
||||
};
|
||||
|
||||
|
|
|
@ -147,15 +147,17 @@ Gfx::IntPoint WebViewBridge::to_widget_position(Gfx::IntPoint content_position)
|
|||
return scale_for_device(content_position, inverse_device_pixel_ratio());
|
||||
}
|
||||
|
||||
void WebViewBridge::initialize_client(CreateNewClient)
|
||||
void WebViewBridge::initialize_client(CreateNewClient create_new_client)
|
||||
{
|
||||
VERIFY(on_request_web_content);
|
||||
|
||||
// FIXME: Don't create a new process when CreateNewClient is false
|
||||
// We should create a new tab/window in the UI instead, and re-use the existing WebContentClient object.
|
||||
m_client_state = {};
|
||||
if (create_new_client == CreateNewClient::Yes) {
|
||||
m_client_state = {};
|
||||
m_client_state.client = on_request_web_content();
|
||||
} else {
|
||||
m_client_state.client->register_view(m_client_state.page_index, *this);
|
||||
}
|
||||
|
||||
m_client_state.client = on_request_web_content();
|
||||
m_client_state.client->on_web_content_process_crash = [this] {
|
||||
Core::deferred_invoke([this] {
|
||||
handle_web_content_process_crash();
|
||||
|
@ -184,4 +186,12 @@ void WebViewBridge::initialize_client(CreateNewClient)
|
|||
}
|
||||
}
|
||||
|
||||
void WebViewBridge::initialize_client_as_child(WebViewBridge const& parent, u64 page_index)
|
||||
{
|
||||
m_client_state.client = parent.client();
|
||||
m_client_state.page_index = page_index;
|
||||
|
||||
initialize_client(CreateNewClient::No);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ public:
|
|||
virtual ~WebViewBridge() override;
|
||||
|
||||
virtual void initialize_client(CreateNewClient = CreateNewClient::Yes) override;
|
||||
void initialize_client_as_child(WebViewBridge const& parent, u64 page_index);
|
||||
|
||||
float device_pixel_ratio() const { return m_device_pixel_ratio; }
|
||||
void set_device_pixel_ratio(float device_pixel_ratio);
|
||||
|
|
|
@ -6,12 +6,18 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Types.h>
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@class LadybirdWebView;
|
||||
|
||||
@interface Tab : NSWindow
|
||||
|
||||
- (instancetype)init;
|
||||
- (instancetype)initAsChild:(Tab*)parent
|
||||
pageIndex:(u64)page_index;
|
||||
|
||||
- (void)tabWillClose;
|
||||
|
||||
- (void)openInspector:(id)sender;
|
||||
|
|
|
@ -60,6 +60,19 @@ static constexpr CGFloat const WINDOW_HEIGHT = 800;
|
|||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
auto* web_view = [[LadybirdWebView alloc] init:self];
|
||||
return [self initWithWebView:web_view];
|
||||
}
|
||||
|
||||
- (instancetype)initAsChild:(Tab*)parent
|
||||
pageIndex:(u64)page_index
|
||||
{
|
||||
auto* web_view = [[LadybirdWebView alloc] initAsChild:self parent:[parent web_view] pageIndex:page_index];
|
||||
return [self initWithWebView:web_view];
|
||||
}
|
||||
|
||||
- (instancetype)initWithWebView:(LadybirdWebView*)web_view
|
||||
{
|
||||
auto screen_rect = [[NSScreen mainScreen] frame];
|
||||
auto position_x = (NSWidth(screen_rect) - WINDOW_WIDTH) / 2;
|
||||
|
@ -77,7 +90,7 @@ static constexpr CGFloat const WINDOW_HEIGHT = 800;
|
|||
// Remember last window position
|
||||
self.frameAutosaveName = @"window";
|
||||
|
||||
self.web_view = [[LadybirdWebView alloc] init:self];
|
||||
self.web_view = web_view;
|
||||
[self.web_view setPostsBoundsChangedNotifications:YES];
|
||||
|
||||
self.favicon = [Tab defaultFavicon];
|
||||
|
@ -296,6 +309,21 @@ static constexpr CGFloat const WINDOW_HEIGHT = 800;
|
|||
return [[tab web_view] handle];
|
||||
}
|
||||
|
||||
- (String const&)onCreateChildTab:(Optional<URL::URL> const&)url
|
||||
activateTab:(Web::HTML::ActivateTab)activate_tab
|
||||
pageIndex:(u64)page_index
|
||||
{
|
||||
auto* delegate = (ApplicationDelegate*)[NSApp delegate];
|
||||
|
||||
auto* controller = [delegate createChildTab:url
|
||||
fromTab:self
|
||||
activateTab:activate_tab
|
||||
pageIndex:page_index];
|
||||
|
||||
auto* tab = (Tab*)[controller window];
|
||||
return [[tab web_view] handle];
|
||||
}
|
||||
|
||||
- (void)loadURL:(URL::URL const&)url
|
||||
{
|
||||
[[self tabController] loadURL:url];
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@class Tab;
|
||||
|
||||
struct TabSettings {
|
||||
BOOL should_show_line_box_borders { NO };
|
||||
BOOL scripting_enabled { YES };
|
||||
|
@ -23,6 +25,8 @@ struct TabSettings {
|
|||
@interface TabController : NSWindowController <NSWindowDelegate>
|
||||
|
||||
- (instancetype)init;
|
||||
- (instancetype)initAsChild:(Tab*)parent
|
||||
pageIndex:(u64)page_index;
|
||||
|
||||
- (void)loadURL:(URL::URL const&)url;
|
||||
- (void)loadHTML:(StringView)html url:(URL::URL const&)url;
|
||||
|
|
|
@ -49,6 +49,8 @@ static NSString* const TOOLBAR_TAB_OVERVIEW_IDENTIFIER = @"ToolbarTabOverviewIde
|
|||
|
||||
@interface TabController () <NSToolbarDelegate, NSSearchFieldDelegate>
|
||||
{
|
||||
u64 m_page_index;
|
||||
|
||||
ByteString m_title;
|
||||
|
||||
TabSettings m_settings;
|
||||
|
@ -57,6 +59,8 @@ static NSString* const TOOLBAR_TAB_OVERVIEW_IDENTIFIER = @"ToolbarTabOverviewIde
|
|||
bool m_can_navigate_forward;
|
||||
}
|
||||
|
||||
@property (nonatomic, strong) Tab* parent;
|
||||
|
||||
@property (nonatomic, strong) NSToolbar* toolbar;
|
||||
@property (nonatomic, strong) NSArray* toolbar_identifiers;
|
||||
|
||||
|
@ -92,6 +96,8 @@ static NSString* const TOOLBAR_TAB_OVERVIEW_IDENTIFIER = @"ToolbarTabOverviewIde
|
|||
[self.toolbar setAllowsUserCustomization:NO];
|
||||
[self.toolbar setSizeMode:NSToolbarSizeModeRegular];
|
||||
|
||||
m_page_index = 0;
|
||||
|
||||
m_settings = {
|
||||
.scripting_enabled = WebView::Application::chrome_options().disable_scripting == WebView::DisableScripting::Yes ? NO : YES,
|
||||
.block_popups = WebView::Application::chrome_options().allow_popups == WebView::AllowPopups::Yes ? NO : YES,
|
||||
|
@ -107,6 +113,17 @@ static NSString* const TOOLBAR_TAB_OVERVIEW_IDENTIFIER = @"ToolbarTabOverviewIde
|
|||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initAsChild:(Tab*)parent
|
||||
pageIndex:(u64)page_index
|
||||
{
|
||||
if (self = [self init]) {
|
||||
self.parent = parent;
|
||||
m_page_index = page_index;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Public methods
|
||||
|
||||
- (void)loadURL:(URL::URL const&)url
|
||||
|
@ -544,7 +561,10 @@ static NSString* const TOOLBAR_TAB_OVERVIEW_IDENTIFIER = @"ToolbarTabOverviewIde
|
|||
|
||||
- (IBAction)showWindow:(id)sender
|
||||
{
|
||||
self.window = [[Tab alloc] init];
|
||||
self.window = self.parent
|
||||
? [[Tab alloc] initAsChild:self.parent pageIndex:m_page_index]
|
||||
: [[Tab alloc] init];
|
||||
|
||||
[self.window setDelegate:self];
|
||||
|
||||
[self.window setToolbar:self.toolbar];
|
||||
|
|
Loading…
Reference in a new issue