diff --git a/BUILD.gn b/BUILD.gn index c4a4269815..0988146cbe 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -502,6 +502,7 @@ source_set("electron_lib") { "//ui/native_theme", "//ui/shell_dialogs", "//ui/views", + "//ui/views/controls/webview", "//v8", "//v8:v8_libplatform", ] @@ -637,7 +638,6 @@ source_set("electron_lib") { "//ui/gtk:gtk_config", "//ui/linux:linux_ui", "//ui/linux:linux_ui_factory", - "//ui/views/controls/webview", "//ui/wm", ] if (ozone_platform_x11) { @@ -666,7 +666,6 @@ source_set("electron_lib") { deps += [ "//components/crash/core/app:crash_export_thunks", "//ui/native_theme:native_theme_browser", - "//ui/views/controls/webview", "//ui/wm", "//ui/wm/public", ] diff --git a/filenames.gni b/filenames.gni index e39cb840de..48c94f6099 100644 --- a/filenames.gni +++ b/filenames.gni @@ -155,12 +155,8 @@ filenames = { "shell/browser/osr/osr_web_contents_view_mac.mm", "shell/browser/relauncher_mac.cc", "shell/browser/ui/certificate_trust_mac.mm", - "shell/browser/ui/cocoa/delayed_native_view_host.h", - "shell/browser/ui/cocoa/delayed_native_view_host.mm", "shell/browser/ui/cocoa/electron_bundle_mover.h", "shell/browser/ui/cocoa/electron_bundle_mover.mm", - "shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h", - "shell/browser/ui/cocoa/electron_inspectable_web_contents_view.mm", "shell/browser/ui/cocoa/electron_menu_controller.h", "shell/browser/ui/cocoa/electron_menu_controller.mm", "shell/browser/ui/cocoa/electron_native_widget_mac.h", @@ -187,8 +183,6 @@ filenames = { "shell/browser/ui/cocoa/window_buttons_proxy.mm", "shell/browser/ui/drag_util_mac.mm", "shell/browser/ui/file_dialog_mac.mm", - "shell/browser/ui/inspectable_web_contents_view_mac.h", - "shell/browser/ui/inspectable_web_contents_view_mac.mm", "shell/browser/ui/message_box_mac.mm", "shell/browser/ui/tray_icon_cocoa.h", "shell/browser/ui/tray_icon_cocoa.mm", @@ -204,6 +198,7 @@ filenames = { "shell/common/node_bindings_mac.cc", "shell/common/node_bindings_mac.h", "shell/common/platform_util_mac.mm", + "shell/browser/ui/views/inspectable_web_contents_view_mac.mm", ] lib_sources_views = [ @@ -218,8 +213,6 @@ filenames = { "shell/browser/ui/views/electron_views_delegate.h", "shell/browser/ui/views/frameless_view.cc", "shell/browser/ui/views/frameless_view.h", - "shell/browser/ui/views/inspectable_web_contents_view_views.cc", - "shell/browser/ui/views/inspectable_web_contents_view_views.h", "shell/browser/ui/views/menu_bar.cc", "shell/browser/ui/views/menu_bar.h", "shell/browser/ui/views/menu_delegate.cc", diff --git a/shell/browser/api/electron_api_base_window.cc b/shell/browser/api/electron_api_base_window.cc index 7b040f8cad..d8c1f8063f 100644 --- a/shell/browser/api/electron_api_base_window.cc +++ b/shell/browser/api/electron_api_base_window.cc @@ -117,11 +117,6 @@ BaseWindow::BaseWindow(gin_helper::Arguments* args, BaseWindow::~BaseWindow() { CloseImmediately(); - // Destroy the native window in next tick because the native code might be - // iterating all windows. - base::SingleThreadTaskRunner::GetCurrentDefault()->DeleteSoon( - FROM_HERE, window_.release()); - // Remove global reference so the JS object can be garbage collected. self_ref_.Reset(); } diff --git a/shell/browser/api/electron_api_web_contents_view.cc b/shell/browser/api/electron_api_web_contents_view.cc index 9fbc2e2b8e..c780d107ae 100644 --- a/shell/browser/api/electron_api_web_contents_view.cc +++ b/shell/browser/api/electron_api_web_contents_view.cc @@ -24,29 +24,14 @@ #include "ui/views/view_class_properties.h" #include "ui/views/widget/widget.h" -#if BUILDFLAG(IS_MAC) -#include "shell/browser/ui/cocoa/delayed_native_view_host.h" -#endif - namespace electron::api { WebContentsView::WebContentsView(v8::Isolate* isolate, gin::Handle web_contents) -#if BUILDFLAG(IS_MAC) - : View(new DelayedNativeViewHost(web_contents->inspectable_web_contents() - ->GetView() - ->GetNativeView())), -#else - : View(web_contents->inspectable_web_contents()->GetView()->GetView()), -#endif + : View(web_contents->inspectable_web_contents()->GetView()), web_contents_(isolate, web_contents.ToV8()), api_web_contents_(web_contents.get()) { -#if !BUILDFLAG(IS_MAC) - // On macOS the View is a newly-created |DelayedNativeViewHost| and it is our - // responsibility to delete it. On other platforms the View is created and - // managed by InspectableWebContents. set_delete_view(false); -#endif view()->SetProperty( views::kFlexBehaviorKey, views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToMinimum, diff --git a/shell/browser/native_window_mac.mm b/shell/browser/native_window_mac.mm index 240f69d0c6..f870ba64f9 100644 --- a/shell/browser/native_window_mac.mm +++ b/shell/browser/native_window_mac.mm @@ -242,6 +242,7 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options, params.bounds = bounds; params.delegate = this; params.type = views::Widget::InitParams::TYPE_WINDOW; + params.headless_mode = true; params.native_widget = new ElectronNativeWidgetMac(this, windowType, styleMask, widget()); widget()->Init(std::move(params)); diff --git a/shell/browser/native_window_views.cc b/shell/browser/native_window_views.cc index cd90e0ab99..86dbfc1e9c 100644 --- a/shell/browser/native_window_views.cc +++ b/shell/browser/native_window_views.cc @@ -28,7 +28,7 @@ #include "content/public/browser/desktop_media_id.h" #include "shell/browser/api/electron_api_web_contents.h" #include "shell/browser/ui/inspectable_web_contents.h" -#include "shell/browser/ui/views/inspectable_web_contents_view_views.h" +#include "shell/browser/ui/inspectable_web_contents_view.h" #include "shell/browser/ui/views/root_view.h" #include "shell/browser/web_contents_preferences.h" #include "shell/browser/web_view_manager.h" diff --git a/shell/browser/ui/cocoa/delayed_native_view_host.h b/shell/browser/ui/cocoa/delayed_native_view_host.h deleted file mode 100644 index eb02826c2b..0000000000 --- a/shell/browser/ui/cocoa/delayed_native_view_host.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2018 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#ifndef ELECTRON_SHELL_BROWSER_UI_COCOA_DELAYED_NATIVE_VIEW_HOST_H_ -#define ELECTRON_SHELL_BROWSER_UI_COCOA_DELAYED_NATIVE_VIEW_HOST_H_ - -#include "ui/views/controls/native/native_view_host.h" - -namespace electron { - -// Automatically attach the native view after the NativeViewHost is attached to -// a widget. (Attaching it directly would cause crash.) -class DelayedNativeViewHost : public views::NativeViewHost { - public: - explicit DelayedNativeViewHost(gfx::NativeView native_view); - ~DelayedNativeViewHost() override; - - // disable copy - DelayedNativeViewHost(const DelayedNativeViewHost&) = delete; - DelayedNativeViewHost& operator=(const DelayedNativeViewHost&) = delete; - - // views::View: - void ViewHierarchyChanged( - const views::ViewHierarchyChangedDetails& details) override; - bool OnMousePressed(const ui::MouseEvent& event) override; - - private: - gfx::NativeView native_view_; -}; - -} // namespace electron - -#endif // ELECTRON_SHELL_BROWSER_UI_COCOA_DELAYED_NATIVE_VIEW_HOST_H_ diff --git a/shell/browser/ui/cocoa/delayed_native_view_host.mm b/shell/browser/ui/cocoa/delayed_native_view_host.mm deleted file mode 100644 index e8f4f0305d..0000000000 --- a/shell/browser/ui/cocoa/delayed_native_view_host.mm +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2018 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "shell/browser/ui/cocoa/delayed_native_view_host.h" -#include "base/apple/owned_objc.h" -#include "shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h" - -namespace electron { - -DelayedNativeViewHost::DelayedNativeViewHost(gfx::NativeView native_view) - : native_view_(native_view) {} - -DelayedNativeViewHost::~DelayedNativeViewHost() = default; - -void DelayedNativeViewHost::ViewHierarchyChanged( - const views::ViewHierarchyChangedDetails& details) { - // NativeViewHost doesn't expect to have children, so filter the - // ViewHierarchyChanged events before passing them on. - if (details.child == this) { - NativeViewHost::ViewHierarchyChanged(details); - if (details.is_add && GetWidget() && !native_view()) - Attach(native_view_); - } -} - -bool DelayedNativeViewHost::OnMousePressed(const ui::MouseEvent& ui_event) { - // NativeViewHost::OnMousePressed normally isn't called, but - // NativeWidgetMacNSWindow specifically carves out an event here for - // right-mouse-button clicks. We want to forward them to the web content, so - // handle them here. - // See: - // https://source.chromium.org/chromium/chromium/src/+/main:components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm;l=415-421;drc=a5af91924bafb85426e091c6035801990a6dc697 - - ElectronInspectableWebContentsView* inspectable_web_contents_view = - (ElectronInspectableWebContentsView*)native_view_.GetNativeNSView(); - [inspectable_web_contents_view - redispatchContextMenuEvent:base::apple::OwnedNSEvent( - ui_event.native_event())]; - - return true; -} - -} // namespace electron diff --git a/shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h b/shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h deleted file mode 100644 index ea7de51839..0000000000 --- a/shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-CHROMIUM file. - -#ifndef ELECTRON_SHELL_BROWSER_UI_COCOA_ELECTRON_INSPECTABLE_WEB_CONTENTS_VIEW_H_ -#define ELECTRON_SHELL_BROWSER_UI_COCOA_ELECTRON_INSPECTABLE_WEB_CONTENTS_VIEW_H_ - -#import - -#include "base/apple/owned_objc.h" -#include "base/memory/raw_ptr.h" -#include "chrome/browser/devtools/devtools_contents_resizing_strategy.h" -#include "ui/base/cocoa/base_view.h" - -namespace electron { -class InspectableWebContentsViewMac; -} - -using electron::InspectableWebContentsViewMac; - -@interface NSView (WebContentsView) -- (void)setMouseDownCanMoveWindow:(BOOL)can_move; -@end - -@interface ElectronInspectableWebContentsView : BaseView { - @private - raw_ptr inspectableWebContentsView_; - - NSView* __strong fake_view_; - NSWindow* __strong devtools_window_; - BOOL devtools_visible_; - BOOL devtools_docked_; - BOOL devtools_is_first_responder_; - BOOL attached_to_window_; - - DevToolsContentsResizingStrategy strategy_; -} - -- (instancetype)initWithInspectableWebContentsViewMac: - (InspectableWebContentsViewMac*)view; -- (void)notifyDevToolsFocused; -- (void)setDevToolsVisible:(BOOL)visible activate:(BOOL)activate; -- (BOOL)isDevToolsVisible; -- (BOOL)isDevToolsFocused; -- (void)setIsDocked:(BOOL)docked activate:(BOOL)activate; -- (void)setContentsResizingStrategy: - (const DevToolsContentsResizingStrategy&)strategy; -- (void)setTitle:(NSString*)title; -- (NSString*)getTitle; - -- (void)redispatchContextMenuEvent:(base::apple::OwnedNSEvent)theEvent; - -@end - -#endif // ELECTRON_SHELL_BROWSER_UI_COCOA_ELECTRON_INSPECTABLE_WEB_CONTENTS_VIEW_H_ diff --git a/shell/browser/ui/cocoa/electron_inspectable_web_contents_view.mm b/shell/browser/ui/cocoa/electron_inspectable_web_contents_view.mm deleted file mode 100644 index 809ca9a9f8..0000000000 --- a/shell/browser/ui/cocoa/electron_inspectable_web_contents_view.mm +++ /dev/null @@ -1,340 +0,0 @@ -// Copyright (c) 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-CHROMIUM file. - -#include "shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h" - -#include "content/public/browser/render_widget_host_view.h" -#include "shell/browser/api/electron_api_web_contents.h" -#include "shell/browser/ui/cocoa/event_dispatching_window.h" -#include "shell/browser/ui/inspectable_web_contents.h" -#include "shell/browser/ui/inspectable_web_contents_view_delegate.h" -#include "shell/browser/ui/inspectable_web_contents_view_mac.h" -#include "ui/base/cocoa/base_view.h" -#include "ui/gfx/mac/scoped_cocoa_disable_screen_updates.h" - -@implementation ElectronInspectableWebContentsView - -- (instancetype)initWithInspectableWebContentsViewMac: - (InspectableWebContentsViewMac*)view { - self = [super init]; - if (!self) - return nil; - - inspectableWebContentsView_ = view; - devtools_visible_ = NO; - devtools_docked_ = NO; - devtools_is_first_responder_ = NO; - attached_to_window_ = NO; - - if (inspectableWebContentsView_->inspectable_web_contents()->is_guest()) { - fake_view_ = [[NSView alloc] init]; - [fake_view_ setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - [self addSubview:fake_view_]; - } else { - auto* contents = inspectableWebContentsView_->inspectable_web_contents() - ->GetWebContents(); - auto* contentsView = contents->GetNativeView().GetNativeNSView(); - [contentsView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - [self addSubview:contentsView]; - } - - // See https://code.google.com/p/chromium/issues/detail?id=348490. - [self setWantsLayer:YES]; - - return self; -} - -- (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -- (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize { - [self adjustSubviews]; -} - -- (void)viewDidMoveToWindow { - if (attached_to_window_ && !self.window) { - attached_to_window_ = NO; - [[NSNotificationCenter defaultCenter] removeObserver:self]; - } else if (!attached_to_window_ && self.window) { - attached_to_window_ = YES; - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(viewDidBecomeFirstResponder:) - name:kViewDidBecomeFirstResponder - object:nil]; - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(parentWindowBecameMain:) - name:NSWindowDidBecomeMainNotification - object:nil]; - } -} - -- (IBAction)showDevTools:(id)sender { - inspectableWebContentsView_->inspectable_web_contents()->ShowDevTools(true); -} - -- (void)notifyDevToolsFocused { - if (inspectableWebContentsView_->GetDelegate()) - inspectableWebContentsView_->GetDelegate()->DevToolsFocused(); -} - -- (void)notifyDevToolsResized { - // When devtools is opened, resizing devtools would not trigger - // UpdateDraggableRegions for WebContents, so we have to notify the window - // to do an update of draggable regions. - if (inspectableWebContentsView_->GetDelegate()) - inspectableWebContentsView_->GetDelegate()->DevToolsResized(); -} - -- (void)setDevToolsVisible:(BOOL)visible activate:(BOOL)activate { - if (visible == devtools_visible_) - return; - - auto* inspectable_web_contents = - inspectableWebContentsView_->inspectable_web_contents(); - auto* devToolsWebContents = - inspectable_web_contents->GetDevToolsWebContents(); - auto* devToolsView = devToolsWebContents->GetNativeView().GetNativeNSView(); - - devtools_visible_ = visible; - if (devtools_docked_) { - if (visible) { - // Place the devToolsView under contentsView, notice that we didn't set - // sizes for them until the setContentsResizingStrategy message. - [self addSubview:devToolsView positioned:NSWindowBelow relativeTo:nil]; - [self adjustSubviews]; - - // Focus on web view. - devToolsWebContents->RestoreFocus(); - } else { - gfx::ScopedCocoaDisableScreenUpdates disabler; - [devToolsView removeFromSuperview]; - [self adjustSubviews]; - [self notifyDevToolsResized]; - } - } else { - if (visible) { - if (activate) { - [devtools_window_ makeKeyAndOrderFront:nil]; - } else { - [devtools_window_ orderBack:nil]; - } - } else { - [devtools_window_ setDelegate:nil]; - [devtools_window_ close]; - devtools_window_ = nil; - } - } -} - -- (BOOL)isDevToolsVisible { - return devtools_visible_; -} - -- (BOOL)isDevToolsFocused { - if (devtools_docked_) { - return [[self window] isKeyWindow] && devtools_is_first_responder_; - } else { - return [devtools_window_ isKeyWindow]; - } -} - -- (void)setIsDocked:(BOOL)docked activate:(BOOL)activate { - // Revert to no-devtools state. - [self setDevToolsVisible:NO activate:NO]; - - // Switch to new state. - devtools_docked_ = docked; - auto* inspectable_web_contents = - inspectableWebContentsView_->inspectable_web_contents(); - auto* devToolsWebContents = - inspectable_web_contents->GetDevToolsWebContents(); - auto devToolsView = devToolsWebContents->GetNativeView().GetNativeNSView(); - if (!docked) { - auto styleMask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | - NSWindowStyleMaskMiniaturizable | - NSWindowStyleMaskResizable | - NSWindowStyleMaskTexturedBackground | - NSWindowStyleMaskUnifiedTitleAndToolbar; - devtools_window_ = [[EventDispatchingWindow alloc] - initWithContentRect:NSMakeRect(0, 0, 800, 600) - styleMask:styleMask - backing:NSBackingStoreBuffered - defer:YES]; - [devtools_window_ setDelegate:self]; - [devtools_window_ setFrameAutosaveName:@"electron.devtools"]; - [devtools_window_ setTitle:@"Developer Tools"]; - [devtools_window_ setReleasedWhenClosed:NO]; - [devtools_window_ setAutorecalculatesContentBorderThickness:NO - forEdge:NSMaxYEdge]; - [devtools_window_ setContentBorderThickness:24 forEdge:NSMaxYEdge]; - - NSView* contentView = [devtools_window_ contentView]; - devToolsView.frame = contentView.bounds; - devToolsView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; - - [contentView addSubview:devToolsView]; - [devToolsView setMouseDownCanMoveWindow:NO]; - } else { - [devToolsView setMouseDownCanMoveWindow:YES]; - } - [self setDevToolsVisible:YES activate:activate]; -} - -- (void)setContentsResizingStrategy: - (const DevToolsContentsResizingStrategy&)strategy { - strategy_.CopyFrom(strategy); - [self adjustSubviews]; -} - -- (void)adjustSubviews { - if (![[self subviews] count]) - return; - - if (![self isDevToolsVisible] || devtools_window_) { - DCHECK_EQ(1u, [[self subviews] count]); - NSView* contents = [[self subviews] objectAtIndex:0]; - [contents setFrame:[self bounds]]; - return; - } - - NSView* devToolsView = [[self subviews] objectAtIndex:0]; - NSView* contentsView = [[self subviews] objectAtIndex:1]; - - DCHECK_EQ(2u, [[self subviews] count]); - - gfx::Rect new_devtools_bounds; - gfx::Rect new_contents_bounds; - ApplyDevToolsContentsResizingStrategy( - strategy_, gfx::Size(NSSizeToCGSize([self bounds].size)), - &new_devtools_bounds, &new_contents_bounds); - [devToolsView setFrame:[self flipRectToNSRect:new_devtools_bounds]]; - [contentsView setFrame:[self flipRectToNSRect:new_contents_bounds]]; - - // Move mask to the devtools area to exclude it from dragging. - NSRect cf = contentsView.frame; - NSRect sb = [self bounds]; - NSRect devtools_frame; - if (cf.size.height < sb.size.height) { // bottom docked - devtools_frame.origin.x = 0; - devtools_frame.origin.y = 0; - devtools_frame.size.width = sb.size.width; - devtools_frame.size.height = sb.size.height - cf.size.height; - } else { // left or right docked - if (cf.origin.x > 0) // left docked - devtools_frame.origin.x = 0; - else // right docked. - devtools_frame.origin.x = cf.size.width; - devtools_frame.origin.y = 0; - devtools_frame.size.width = sb.size.width - cf.size.width; - devtools_frame.size.height = sb.size.height; - } - - [self notifyDevToolsResized]; -} - -- (void)setTitle:(NSString*)title { - [devtools_window_ setTitle:title]; -} - -- (NSString*)getTitle { - return [devtools_window_ title]; -} - -- (void)viewDidBecomeFirstResponder:(NSNotification*)notification { - auto* inspectable_web_contents = - inspectableWebContentsView_->inspectable_web_contents(); - DCHECK(inspectable_web_contents); - auto* webContents = inspectable_web_contents->GetWebContents(); - if (!webContents) - return; - auto* webContentsView = webContents->GetNativeView().GetNativeNSView(); - - NSView* view = [notification object]; - if ([[webContentsView subviews] containsObject:view]) { - devtools_is_first_responder_ = NO; - return; - } - - auto* devToolsWebContents = - inspectable_web_contents->GetDevToolsWebContents(); - if (!devToolsWebContents) - return; - auto devToolsView = devToolsWebContents->GetNativeView().GetNativeNSView(); - - if ([[devToolsView subviews] containsObject:view]) { - devtools_is_first_responder_ = YES; - [self notifyDevToolsFocused]; - } -} - -- (void)parentWindowBecameMain:(NSNotification*)notification { - NSWindow* parentWindow = [notification object]; - if ([self window] == parentWindow && devtools_docked_ && - devtools_is_first_responder_) - [self notifyDevToolsFocused]; -} - -- (void)redispatchContextMenuEvent:(base::apple::OwnedNSEvent)event { - DCHECK(event.Get().type == NSEventTypeRightMouseDown || - (event.Get().type == NSEventTypeLeftMouseDown && - (event.Get().modifierFlags & NSEventModifierFlagControl))); - content::WebContents* contents = - inspectableWebContentsView_->inspectable_web_contents()->GetWebContents(); - electron::api::WebContents* api_contents = - electron::api::WebContents::From(contents); - if (api_contents) { - // Temporarily pretend that the WebContents is fully non-draggable while we - // re-send the mouse event. This allows the re-dispatched event to "land" - // on the WebContents, instead of "falling through" back to the window. - auto* rwhv = contents->GetRenderWidgetHostView(); - if (rwhv) { - api_contents->SetForceNonDraggable(true); - BaseView* contentsView = - (BaseView*)rwhv->GetNativeView().GetNativeNSView(); - [contentsView mouseEvent:event.Get()]; - api_contents->SetForceNonDraggable(false); - } - } -} - -#pragma mark - NSWindowDelegate - -- (void)windowWillClose:(NSNotification*)notification { - inspectableWebContentsView_->inspectable_web_contents()->CloseDevTools(); -} - -- (void)windowDidBecomeMain:(NSNotification*)notification { - content::WebContents* web_contents = - inspectableWebContentsView_->inspectable_web_contents() - ->GetDevToolsWebContents(); - if (!web_contents) - return; - - web_contents->RestoreFocus(); - - content::RenderWidgetHostView* rwhv = web_contents->GetRenderWidgetHostView(); - if (rwhv) - rwhv->SetActive(true); - - [self notifyDevToolsFocused]; -} - -- (void)windowDidResignMain:(NSNotification*)notification { - content::WebContents* web_contents = - inspectableWebContentsView_->inspectable_web_contents() - ->GetDevToolsWebContents(); - if (!web_contents) - return; - - web_contents->StoreFocus(); - - content::RenderWidgetHostView* rwhv = web_contents->GetRenderWidgetHostView(); - if (rwhv) - rwhv->SetActive(false); -} - -@end diff --git a/shell/browser/ui/cocoa/electron_ns_window.mm b/shell/browser/ui/cocoa/electron_ns_window.mm index 17adef63de..96d29893e0 100644 --- a/shell/browser/ui/cocoa/electron_ns_window.mm +++ b/shell/browser/ui/cocoa/electron_ns_window.mm @@ -200,6 +200,11 @@ void SwizzleSwipeWithEvent(NSView* view, SEL swiz_selector) { } - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen*)screen { + // We initialize the window in headless mode to allow painting before it is + // shown, but we don't want the headless behavior of allowing the window to be + // placed unconstrained. + self.isHeadless = false; + // Resizing is disabled. if (electron::ScopedDisableResize::IsResizeDisabled()) return [self frame]; diff --git a/shell/browser/ui/inspectable_web_contents.cc b/shell/browser/ui/inspectable_web_contents.cc index d8c7e14600..2bd232e573 100644 --- a/shell/browser/ui/inspectable_web_contents.cc +++ b/shell/browser/ui/inspectable_web_contents.cc @@ -300,11 +300,6 @@ class InspectableWebContents::NetworkResourceLoader base::TimeDelta retry_delay_; }; -// Implemented separately on each platform. -InspectableWebContentsView* CreateInspectableContentsView( - InspectableWebContents* inspectable_web_contents); - -// static // static void InspectableWebContents::RegisterPrefs(PrefRegistrySimple* registry) { registry->RegisterDictionaryPref(kDevToolsBoundsPref, @@ -320,7 +315,7 @@ InspectableWebContents::InspectableWebContents( : pref_service_(pref_service), web_contents_(std::move(web_contents)), is_guest_(is_guest), - view_(CreateInspectableContentsView(this)) { + view_(new InspectableWebContentsView(this)) { const base::Value* bounds_dict = &pref_service_->GetValue(kDevToolsBoundsPref); if (bounds_dict->is_dict()) { diff --git a/shell/browser/ui/inspectable_web_contents_view.cc b/shell/browser/ui/inspectable_web_contents_view.cc index 946b5071bc..411c902fd1 100644 --- a/shell/browser/ui/inspectable_web_contents_view.cc +++ b/shell/browser/ui/inspectable_web_contents_view.cc @@ -5,12 +5,235 @@ #include "shell/browser/ui/inspectable_web_contents_view.h" +#include +#include + +#include "base/memory/raw_ptr.h" +#include "base/strings/utf_string_conversions.h" +#include "shell/browser/ui/drag_util.h" +#include "shell/browser/ui/inspectable_web_contents.h" +#include "shell/browser/ui/inspectable_web_contents_delegate.h" +#include "shell/browser/ui/inspectable_web_contents_view_delegate.h" +#include "ui/base/models/image_model.h" +#include "ui/views/controls/label.h" +#include "ui/views/controls/webview/webview.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_delegate.h" +#include "ui/views/window/client_view.h" + namespace electron { +namespace { + +class DevToolsWindowDelegate : public views::ClientView, + public views::WidgetDelegate { + public: + DevToolsWindowDelegate(InspectableWebContentsView* shell, + views::View* view, + views::Widget* widget) + : views::ClientView(widget, view), + shell_(shell), + view_(view), + widget_(widget) { + SetOwnedByWidget(true); + set_owned_by_client(); + + if (shell->GetDelegate()) + icon_ = shell->GetDelegate()->GetDevToolsWindowIcon(); + } + ~DevToolsWindowDelegate() override = default; + + // disable copy + DevToolsWindowDelegate(const DevToolsWindowDelegate&) = delete; + DevToolsWindowDelegate& operator=(const DevToolsWindowDelegate&) = delete; + + // views::WidgetDelegate: + views::View* GetInitiallyFocusedView() override { return view_; } + std::u16string GetWindowTitle() const override { return shell_->GetTitle(); } + ui::ImageModel GetWindowAppIcon() override { return GetWindowIcon(); } + ui::ImageModel GetWindowIcon() override { return icon_; } + views::Widget* GetWidget() override { return widget_; } + const views::Widget* GetWidget() const override { return widget_; } + views::View* GetContentsView() override { return view_; } + views::ClientView* CreateClientView(views::Widget* widget) override { + return this; + } + + // views::ClientView: + views::CloseRequestResult OnWindowCloseRequested() override { + shell_->inspectable_web_contents()->CloseDevTools(); + return views::CloseRequestResult::kCannotClose; + } + + private: + raw_ptr shell_; + raw_ptr view_; + raw_ptr widget_; + ui::ImageModel icon_; +}; + +} // namespace + InspectableWebContentsView::InspectableWebContentsView( InspectableWebContents* inspectable_web_contents) - : inspectable_web_contents_(inspectable_web_contents) {} + : inspectable_web_contents_(inspectable_web_contents), + devtools_web_view_(new views::WebView(nullptr)), + title_(u"Developer Tools") { + if (!inspectable_web_contents_->is_guest() && + inspectable_web_contents_->GetWebContents()->GetNativeView()) { + auto* contents_web_view = new views::WebView(nullptr); + contents_web_view->SetWebContents( + inspectable_web_contents_->GetWebContents()); + contents_web_view_ = contents_web_view; + } else { + contents_web_view_ = new views::Label(u"No content under offscreen mode"); + } -InspectableWebContentsView::~InspectableWebContentsView() = default; + devtools_web_view_->SetVisible(false); + AddChildView(devtools_web_view_.get()); + AddChildView(contents_web_view_.get()); +} + +InspectableWebContentsView::~InspectableWebContentsView() { + if (devtools_window_) + inspectable_web_contents()->SaveDevToolsBounds( + devtools_window_->GetWindowBoundsInScreen()); +} + +void InspectableWebContentsView::ShowDevTools(bool activate) { + if (devtools_visible_) + return; + + devtools_visible_ = true; + if (devtools_window_) { + devtools_window_web_view_->SetWebContents( + inspectable_web_contents_->GetDevToolsWebContents()); + devtools_window_->SetBounds(inspectable_web_contents()->dev_tools_bounds()); + if (activate) { + devtools_window_->Show(); + } else { + devtools_window_->ShowInactive(); + } + + // Update draggable regions to account for the new dock position. + if (GetDelegate()) + GetDelegate()->DevToolsResized(); + } else { + devtools_web_view_->SetVisible(true); + devtools_web_view_->SetWebContents( + inspectable_web_contents_->GetDevToolsWebContents()); + devtools_web_view_->RequestFocus(); + DeprecatedLayoutImmediately(); + } +} + +void InspectableWebContentsView::CloseDevTools() { + if (!devtools_visible_) + return; + + devtools_visible_ = false; + if (devtools_window_) { + auto save_bounds = devtools_window_->IsMinimized() + ? devtools_window_->GetRestoredBounds() + : devtools_window_->GetWindowBoundsInScreen(); + inspectable_web_contents()->SaveDevToolsBounds(save_bounds); + + devtools_window_.reset(); + devtools_window_web_view_ = nullptr; + devtools_window_delegate_ = nullptr; + } else { + devtools_web_view_->SetVisible(false); + devtools_web_view_->SetWebContents(nullptr); + DeprecatedLayoutImmediately(); + } +} + +bool InspectableWebContentsView::IsDevToolsViewShowing() { + return devtools_visible_; +} + +bool InspectableWebContentsView::IsDevToolsViewFocused() { + if (devtools_window_web_view_) + return devtools_window_web_view_->HasFocus(); + else if (devtools_web_view_) + return devtools_web_view_->HasFocus(); + else + return false; +} + +void InspectableWebContentsView::SetIsDocked(bool docked, bool activate) { + CloseDevTools(); + + if (!docked) { + devtools_window_ = std::make_unique(); + devtools_window_web_view_ = new views::WebView(nullptr); + devtools_window_delegate_ = new DevToolsWindowDelegate( + this, devtools_window_web_view_, devtools_window_.get()); + + views::Widget::InitParams params; + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + params.delegate = devtools_window_delegate_; + params.bounds = inspectable_web_contents()->dev_tools_bounds(); + +#if BUILDFLAG(IS_LINUX) + params.wm_role_name = "devtools"; + if (GetDelegate()) + GetDelegate()->GetDevToolsWindowWMClass(¶ms.wm_class_name, + ¶ms.wm_class_class); +#endif + + devtools_window_->Init(std::move(params)); + devtools_window_->UpdateWindowIcon(); + devtools_window_->widget_delegate()->SetHasWindowSizeControls(true); + } + + ShowDevTools(activate); +} + +void InspectableWebContentsView::SetContentsResizingStrategy( + const DevToolsContentsResizingStrategy& strategy) { + strategy_.CopyFrom(strategy); + DeprecatedLayoutImmediately(); +} + +void InspectableWebContentsView::SetTitle(const std::u16string& title) { + if (devtools_window_) { + title_ = title; + devtools_window_->UpdateWindowTitle(); + } +} + +const std::u16string InspectableWebContentsView::GetTitle() { + return title_; +} + +void InspectableWebContentsView::Layout(PassKey) { + if (!devtools_web_view_->GetVisible()) { + contents_web_view_->SetBoundsRect(GetContentsBounds()); + // Propagate layout call to all children, for example browser views. + LayoutSuperclass(this); + return; + } + + gfx::Size container_size(width(), height()); + gfx::Rect new_devtools_bounds; + gfx::Rect new_contents_bounds; + ApplyDevToolsContentsResizingStrategy( + strategy_, container_size, &new_devtools_bounds, &new_contents_bounds); + + // DevTools cares about the specific position, so we have to compensate RTL + // layout here. + new_devtools_bounds.set_x(GetMirroredXForRect(new_devtools_bounds)); + new_contents_bounds.set_x(GetMirroredXForRect(new_contents_bounds)); + + devtools_web_view_->SetBoundsRect(new_devtools_bounds); + contents_web_view_->SetBoundsRect(new_contents_bounds); + + // Propagate layout call to all children, for example browser views. + LayoutSuperclass(this); + + if (GetDelegate()) + GetDelegate()->DevToolsResized(); +} } // namespace electron diff --git a/shell/browser/ui/inspectable_web_contents_view.h b/shell/browser/ui/inspectable_web_contents_view.h index c18b8a1de0..49eafbbd0f 100644 --- a/shell/browser/ui/inspectable_web_contents_view.h +++ b/shell/browser/ui/inspectable_web_contents_view.h @@ -9,27 +9,28 @@ #include #include "base/memory/raw_ptr.h" +#include "chrome/browser/devtools/devtools_contents_resizing_strategy.h" #include "electron/shell/common/api/api.mojom.h" #include "ui/gfx/native_widget_types.h" +#include "ui/views/view.h" class DevToolsContentsResizingStrategy; - -#if defined(TOOLKIT_VIEWS) namespace views { -class View; -} -#endif +class WebView; +class Widget; +class WidgetDelegate; +} // namespace views namespace electron { class InspectableWebContents; class InspectableWebContentsViewDelegate; -class InspectableWebContentsView { +class InspectableWebContentsView : public views::View { public: explicit InspectableWebContentsView( InspectableWebContents* inspectable_web_contents); - virtual ~InspectableWebContentsView(); + ~InspectableWebContentsView() override; InspectableWebContents* inspectable_web_contents() { return inspectable_web_contents_; @@ -41,31 +42,38 @@ class InspectableWebContentsView { } InspectableWebContentsViewDelegate* GetDelegate() const { return delegate_; } -#if defined(TOOLKIT_VIEWS) && !BUILDFLAG(IS_MAC) - // Returns the container control, which has devtools view attached. - virtual views::View* GetView() = 0; -#else - virtual gfx::NativeView GetNativeView() const = 0; + void ShowDevTools(bool activate); + void CloseDevTools(); + bool IsDevToolsViewShowing(); + bool IsDevToolsViewFocused(); + void SetIsDocked(bool docked, bool activate); + void SetContentsResizingStrategy( + const DevToolsContentsResizingStrategy& strategy); + void SetTitle(const std::u16string& title); + const std::u16string GetTitle(); + + // views::View: + void Layout(PassKey) override; +#if BUILDFLAG(IS_MAC) + bool OnMousePressed(const ui::MouseEvent& event) override; #endif - virtual void ShowDevTools(bool activate) = 0; - // Hide the DevTools view. - virtual void CloseDevTools() = 0; - virtual bool IsDevToolsViewShowing() = 0; - virtual bool IsDevToolsViewFocused() = 0; - virtual void SetIsDocked(bool docked, bool activate) = 0; - virtual void SetContentsResizingStrategy( - const DevToolsContentsResizingStrategy& strategy) = 0; - virtual void SetTitle(const std::u16string& title) = 0; - virtual const std::u16string GetTitle() = 0; - - protected: + private: // Owns us. raw_ptr inspectable_web_contents_; - private: raw_ptr delegate_ = nullptr; // weak references. + + std::unique_ptr devtools_window_; + raw_ptr devtools_window_web_view_ = nullptr; + raw_ptr contents_web_view_ = nullptr; + raw_ptr devtools_web_view_ = nullptr; + + DevToolsContentsResizingStrategy strategy_; + bool devtools_visible_ = false; + raw_ptr devtools_window_delegate_ = nullptr; + std::u16string title_; }; } // namespace electron diff --git a/shell/browser/ui/inspectable_web_contents_view_mac.h b/shell/browser/ui/inspectable_web_contents_view_mac.h deleted file mode 100644 index e4a7add218..0000000000 --- a/shell/browser/ui/inspectable_web_contents_view_mac.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Copyright (c) 2013 Adam Roben . All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-CHROMIUM file. - -#ifndef ELECTRON_SHELL_BROWSER_UI_INSPECTABLE_WEB_CONTENTS_VIEW_MAC_H_ -#define ELECTRON_SHELL_BROWSER_UI_INSPECTABLE_WEB_CONTENTS_VIEW_MAC_H_ - -#include "shell/browser/ui/inspectable_web_contents_view.h" - -@class ElectronInspectableWebContentsView; - -namespace electron { - -class InspectableWebContentsViewMac : public InspectableWebContentsView { - public: - explicit InspectableWebContentsViewMac( - InspectableWebContents* inspectable_web_contents); - InspectableWebContentsViewMac(const InspectableWebContentsViewMac&) = delete; - InspectableWebContentsViewMac& operator=( - const InspectableWebContentsViewMac&) = delete; - ~InspectableWebContentsViewMac() override; - - gfx::NativeView GetNativeView() const override; - void ShowDevTools(bool activate) override; - void CloseDevTools() override; - bool IsDevToolsViewShowing() override; - bool IsDevToolsViewFocused() override; - void SetIsDocked(bool docked, bool activate) override; - void SetContentsResizingStrategy( - const DevToolsContentsResizingStrategy& strategy) override; - void SetTitle(const std::u16string& title) override; - const std::u16string GetTitle() override; - - private: - ElectronInspectableWebContentsView* __strong view_; -}; - -} // namespace electron - -#endif // ELECTRON_SHELL_BROWSER_UI_INSPECTABLE_WEB_CONTENTS_VIEW_MAC_H_ diff --git a/shell/browser/ui/inspectable_web_contents_view_mac.mm b/shell/browser/ui/inspectable_web_contents_view_mac.mm deleted file mode 100644 index 028aab4bf2..0000000000 --- a/shell/browser/ui/inspectable_web_contents_view_mac.mm +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Copyright (c) 2013 Adam Roben . All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-CHROMIUM file. - -#include "shell/browser/ui/inspectable_web_contents_view_mac.h" - -#include "base/strings/sys_string_conversions.h" -#import "shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h" -#include "shell/browser/ui/inspectable_web_contents.h" -#include "shell/browser/ui/inspectable_web_contents_view_delegate.h" - -namespace electron { - -InspectableWebContentsView* CreateInspectableContentsView( - InspectableWebContents* inspectable_web_contents) { - return new InspectableWebContentsViewMac(inspectable_web_contents); -} - -InspectableWebContentsViewMac::InspectableWebContentsViewMac( - InspectableWebContents* inspectable_web_contents) - : InspectableWebContentsView(inspectable_web_contents), - view_([[ElectronInspectableWebContentsView alloc] - initWithInspectableWebContentsViewMac:this]) {} - -InspectableWebContentsViewMac::~InspectableWebContentsViewMac() { - [[NSNotificationCenter defaultCenter] removeObserver:view_]; - CloseDevTools(); -} - -gfx::NativeView InspectableWebContentsViewMac::GetNativeView() const { - return view_; -} - -void InspectableWebContentsViewMac::ShowDevTools(bool activate) { - [view_ setDevToolsVisible:YES activate:activate]; -} - -void InspectableWebContentsViewMac::CloseDevTools() { - [view_ setDevToolsVisible:NO activate:NO]; -} - -bool InspectableWebContentsViewMac::IsDevToolsViewShowing() { - return [view_ isDevToolsVisible]; -} - -bool InspectableWebContentsViewMac::IsDevToolsViewFocused() { - return [view_ isDevToolsFocused]; -} - -void InspectableWebContentsViewMac::SetIsDocked(bool docked, bool activate) { - [view_ setIsDocked:docked activate:activate]; -} - -void InspectableWebContentsViewMac::SetContentsResizingStrategy( - const DevToolsContentsResizingStrategy& strategy) { - [view_ setContentsResizingStrategy:strategy]; -} - -void InspectableWebContentsViewMac::SetTitle(const std::u16string& title) { - [view_ setTitle:base::SysUTF16ToNSString(title)]; -} - -const std::u16string InspectableWebContentsViewMac::GetTitle() { - return base::SysNSStringToUTF16([view_ getTitle]); -} - -} // namespace electron diff --git a/shell/browser/ui/views/frameless_view.cc b/shell/browser/ui/views/frameless_view.cc index d5c2d54457..ce6cf37251 100644 --- a/shell/browser/ui/views/frameless_view.cc +++ b/shell/browser/ui/views/frameless_view.cc @@ -5,7 +5,7 @@ #include "shell/browser/ui/views/frameless_view.h" #include "shell/browser/native_window_views.h" -#include "shell/browser/ui/views/inspectable_web_contents_view_views.h" +#include "shell/browser/ui/inspectable_web_contents_view.h" #include "ui/aura/window.h" #include "ui/base/hit_test.h" #include "ui/base/metadata/metadata_impl_macros.h" diff --git a/shell/browser/ui/views/inspectable_web_contents_view_mac.mm b/shell/browser/ui/views/inspectable_web_contents_view_mac.mm new file mode 100644 index 0000000000..a98af7cf18 --- /dev/null +++ b/shell/browser/ui/views/inspectable_web_contents_view_mac.mm @@ -0,0 +1,34 @@ +// Copyright (c) 2022 Salesforce, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "shell/browser/ui/inspectable_web_contents_view.h" + +#include "content/public/browser/render_widget_host_view.h" +#include "content/public/browser/web_contents.h" +#include "shell/browser/api/electron_api_web_contents.h" +#include "ui/base/cocoa/base_view.h" + +namespace electron { + +bool InspectableWebContentsView::OnMousePressed(const ui::MouseEvent& event) { + DCHECK(event.IsRightMouseButton() || + (event.IsLeftMouseButton() && event.IsControlDown())); + content::WebContents* contents = inspectable_web_contents()->GetWebContents(); + electron::api::WebContents* api_contents = + electron::api::WebContents::From(contents); + if (api_contents) { + // Temporarily pretend that the WebContents is fully non-draggable while we + // re-send the mouse event. This allows the re-dispatched event to "land" + // on the WebContents, instead of "falling through" back to the window. + api_contents->SetForceNonDraggable(true); + BaseView* contentsView = (BaseView*)contents->GetRenderWidgetHostView() + ->GetNativeView() + .GetNativeNSView(); + [contentsView mouseEvent:event.native_event().Get()]; + api_contents->SetForceNonDraggable(false); + } + return true; +} + +} // namespace electron diff --git a/shell/browser/ui/views/inspectable_web_contents_view_views.cc b/shell/browser/ui/views/inspectable_web_contents_view_views.cc deleted file mode 100644 index 1bdf6e7048..0000000000 --- a/shell/browser/ui/views/inspectable_web_contents_view_views.cc +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright (c) 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-CHROMIUM file. - -#include "shell/browser/ui/views/inspectable_web_contents_view_views.h" - -#include -#include - -#include "base/memory/raw_ptr.h" -#include "base/strings/utf_string_conversions.h" -#include "shell/browser/ui/drag_util.h" -#include "shell/browser/ui/inspectable_web_contents.h" -#include "shell/browser/ui/inspectable_web_contents_delegate.h" -#include "shell/browser/ui/inspectable_web_contents_view_delegate.h" -#include "ui/base/models/image_model.h" -#include "ui/views/controls/label.h" -#include "ui/views/controls/webview/webview.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" -#include "ui/views/window/client_view.h" - -namespace electron { - -namespace { - -class DevToolsWindowDelegate : public views::ClientView, - public views::WidgetDelegate { - public: - DevToolsWindowDelegate(InspectableWebContentsViewViews* shell, - views::View* view, - views::Widget* widget) - : views::ClientView(widget, view), - shell_(shell), - view_(view), - widget_(widget) { - SetOwnedByWidget(true); - set_owned_by_client(); - - if (shell->GetDelegate()) - icon_ = shell->GetDelegate()->GetDevToolsWindowIcon(); - } - ~DevToolsWindowDelegate() override = default; - - // disable copy - DevToolsWindowDelegate(const DevToolsWindowDelegate&) = delete; - DevToolsWindowDelegate& operator=(const DevToolsWindowDelegate&) = delete; - - // views::WidgetDelegate: - views::View* GetInitiallyFocusedView() override { return view_; } - std::u16string GetWindowTitle() const override { return shell_->GetTitle(); } - ui::ImageModel GetWindowAppIcon() override { return GetWindowIcon(); } - ui::ImageModel GetWindowIcon() override { return icon_; } - views::Widget* GetWidget() override { return widget_; } - const views::Widget* GetWidget() const override { return widget_; } - views::View* GetContentsView() override { return view_; } - views::ClientView* CreateClientView(views::Widget* widget) override { - return this; - } - - // views::ClientView: - views::CloseRequestResult OnWindowCloseRequested() override { - shell_->inspectable_web_contents()->CloseDevTools(); - return views::CloseRequestResult::kCannotClose; - } - - private: - raw_ptr shell_; - raw_ptr view_; - raw_ptr widget_; - ui::ImageModel icon_; -}; - -} // namespace - -InspectableWebContentsView* CreateInspectableContentsView( - InspectableWebContents* inspectable_web_contents) { - return new InspectableWebContentsViewViews(inspectable_web_contents); -} - -InspectableWebContentsViewViews::InspectableWebContentsViewViews( - InspectableWebContents* inspectable_web_contents) - : InspectableWebContentsView(inspectable_web_contents), - devtools_web_view_(new views::WebView(nullptr)), - title_(u"Developer Tools") { - if (!inspectable_web_contents_->is_guest() && - inspectable_web_contents_->GetWebContents()->GetNativeView()) { - auto* contents_web_view = new views::WebView(nullptr); - contents_web_view->SetWebContents( - inspectable_web_contents_->GetWebContents()); - contents_web_view_ = contents_web_view; - } else { - contents_web_view_ = new views::Label(u"No content under offscreen mode"); - } - - devtools_web_view_->SetVisible(false); - AddChildView(devtools_web_view_.get()); - AddChildView(contents_web_view_.get()); -} - -InspectableWebContentsViewViews::~InspectableWebContentsViewViews() { - if (devtools_window_) - inspectable_web_contents()->SaveDevToolsBounds( - devtools_window_->GetWindowBoundsInScreen()); -} - -views::View* InspectableWebContentsViewViews::GetView() { - return this; -} - -void InspectableWebContentsViewViews::ShowDevTools(bool activate) { - if (devtools_visible_) - return; - - devtools_visible_ = true; - if (devtools_window_) { - devtools_window_web_view_->SetWebContents( - inspectable_web_contents_->GetDevToolsWebContents()); - devtools_window_->SetBounds(inspectable_web_contents()->dev_tools_bounds()); - if (activate) { - devtools_window_->Show(); - } else { - devtools_window_->ShowInactive(); - } - - // Update draggable regions to account for the new dock position. - if (GetDelegate()) - GetDelegate()->DevToolsResized(); - } else { - devtools_web_view_->SetVisible(true); - devtools_web_view_->SetWebContents( - inspectable_web_contents_->GetDevToolsWebContents()); - devtools_web_view_->RequestFocus(); - DeprecatedLayoutImmediately(); - } -} - -void InspectableWebContentsViewViews::CloseDevTools() { - if (!devtools_visible_) - return; - - devtools_visible_ = false; - if (devtools_window_) { - auto save_bounds = devtools_window_->IsMinimized() - ? devtools_window_->GetRestoredBounds() - : devtools_window_->GetWindowBoundsInScreen(); - inspectable_web_contents()->SaveDevToolsBounds(save_bounds); - - devtools_window_.reset(); - devtools_window_web_view_ = nullptr; - devtools_window_delegate_ = nullptr; - } else { - devtools_web_view_->SetVisible(false); - devtools_web_view_->SetWebContents(nullptr); - DeprecatedLayoutImmediately(); - } -} - -bool InspectableWebContentsViewViews::IsDevToolsViewShowing() { - return devtools_visible_; -} - -bool InspectableWebContentsViewViews::IsDevToolsViewFocused() { - if (devtools_window_web_view_) - return devtools_window_web_view_->HasFocus(); - else if (devtools_web_view_) - return devtools_web_view_->HasFocus(); - else - return false; -} - -void InspectableWebContentsViewViews::SetIsDocked(bool docked, bool activate) { - CloseDevTools(); - - if (!docked) { - devtools_window_ = std::make_unique(); - devtools_window_web_view_ = new views::WebView(nullptr); - devtools_window_delegate_ = new DevToolsWindowDelegate( - this, devtools_window_web_view_, devtools_window_.get()); - - views::Widget::InitParams params; - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.delegate = devtools_window_delegate_; - params.bounds = inspectable_web_contents()->dev_tools_bounds(); - -#if BUILDFLAG(IS_LINUX) - params.wm_role_name = "devtools"; - if (GetDelegate()) - GetDelegate()->GetDevToolsWindowWMClass(¶ms.wm_class_name, - ¶ms.wm_class_class); -#endif - - devtools_window_->Init(std::move(params)); - devtools_window_->UpdateWindowIcon(); - devtools_window_->widget_delegate()->SetHasWindowSizeControls(true); - } - - ShowDevTools(activate); -} - -void InspectableWebContentsViewViews::SetContentsResizingStrategy( - const DevToolsContentsResizingStrategy& strategy) { - strategy_.CopyFrom(strategy); - DeprecatedLayoutImmediately(); -} - -void InspectableWebContentsViewViews::SetTitle(const std::u16string& title) { - if (devtools_window_) { - title_ = title; - devtools_window_->UpdateWindowTitle(); - } -} - -const std::u16string InspectableWebContentsViewViews::GetTitle() { - return title_; -} - -void InspectableWebContentsViewViews::Layout(PassKey) { - if (!devtools_web_view_->GetVisible()) { - contents_web_view_->SetBoundsRect(GetContentsBounds()); - // Propagate layout call to all children, for example browser views. - LayoutSuperclass(this); - return; - } - - gfx::Size container_size(width(), height()); - gfx::Rect new_devtools_bounds; - gfx::Rect new_contents_bounds; - ApplyDevToolsContentsResizingStrategy( - strategy_, container_size, &new_devtools_bounds, &new_contents_bounds); - - // DevTools cares about the specific position, so we have to compensate RTL - // layout here. - new_devtools_bounds.set_x(GetMirroredXForRect(new_devtools_bounds)); - new_contents_bounds.set_x(GetMirroredXForRect(new_contents_bounds)); - - devtools_web_view_->SetBoundsRect(new_devtools_bounds); - contents_web_view_->SetBoundsRect(new_contents_bounds); - - // Propagate layout call to all children, for example browser views. - LayoutSuperclass(this); - - if (GetDelegate()) - GetDelegate()->DevToolsResized(); -} - -} // namespace electron diff --git a/shell/browser/ui/views/inspectable_web_contents_view_views.h b/shell/browser/ui/views/inspectable_web_contents_view_views.h deleted file mode 100644 index cc7a1d9a81..0000000000 --- a/shell/browser/ui/views/inspectable_web_contents_view_views.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-CHROMIUM file. - -#ifndef ELECTRON_SHELL_BROWSER_UI_VIEWS_INSPECTABLE_WEB_CONTENTS_VIEW_VIEWS_H_ -#define ELECTRON_SHELL_BROWSER_UI_VIEWS_INSPECTABLE_WEB_CONTENTS_VIEW_VIEWS_H_ - -#include - -#include "base/compiler_specific.h" -#include "base/memory/raw_ptr.h" -#include "chrome/browser/devtools/devtools_contents_resizing_strategy.h" -#include "shell/browser/ui/inspectable_web_contents_view.h" -#include "third_party/skia/include/core/SkRegion.h" -#include "ui/views/view.h" - -namespace views { -class WebView; -class Widget; -class WidgetDelegate; -} // namespace views - -namespace electron { - -class InspectableWebContentsViewViews : public InspectableWebContentsView, - public views::View { - public: - explicit InspectableWebContentsViewViews( - InspectableWebContents* inspectable_web_contents); - ~InspectableWebContentsViewViews() override; - - // InspectableWebContentsView: - views::View* GetView() override; - void ShowDevTools(bool activate) override; - void CloseDevTools() override; - bool IsDevToolsViewShowing() override; - bool IsDevToolsViewFocused() override; - void SetIsDocked(bool docked, bool activate) override; - void SetContentsResizingStrategy( - const DevToolsContentsResizingStrategy& strategy) override; - void SetTitle(const std::u16string& title) override; - const std::u16string GetTitle() override; - - // views::View: - void Layout(PassKey) override; - - private: - std::unique_ptr devtools_window_; - raw_ptr devtools_window_web_view_ = nullptr; - raw_ptr contents_web_view_ = nullptr; - raw_ptr devtools_web_view_ = nullptr; - - DevToolsContentsResizingStrategy strategy_; - bool devtools_visible_ = false; - raw_ptr devtools_window_delegate_ = nullptr; - std::u16string title_; -}; - -} // namespace electron - -#endif // ELECTRON_SHELL_BROWSER_UI_VIEWS_INSPECTABLE_WEB_CONTENTS_VIEW_VIEWS_H_