зеркало из https://github.com/electron/electron.git
fix: remove InspectableWebContentsViewMac (#43033)
* Revert "refactor: remove InspectableWebContentsViewMac in favor of the Views version (#41326)"
This reverts commit e67ab9a93d
.
* build: fix gn check
* chore: implement setCornerRadii in inspectable_web_contents_view_mac
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* fix: pass in cornerRadii value in setCornerRadii
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
* fix: forward declaration
* 5578714: Remove 0-arg (default) constructor for views::Widget::InitParams.
https://chromium-review.googlesource.com/c/chromium/src/+/5578714
* fix: contents_web_view_ -> contents_view_
* chore: remove extraneous includes
---------
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
This commit is contained in:
Родитель
b3d52c01e8
Коммит
8db1563d73
|
@ -159,8 +159,12 @@ filenames = {
|
||||||
"shell/browser/osr/osr_web_contents_view_mac.mm",
|
"shell/browser/osr/osr_web_contents_view_mac.mm",
|
||||||
"shell/browser/relauncher_mac.cc",
|
"shell/browser/relauncher_mac.cc",
|
||||||
"shell/browser/ui/certificate_trust_mac.mm",
|
"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.h",
|
||||||
"shell/browser/ui/cocoa/electron_bundle_mover.mm",
|
"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.h",
|
||||||
"shell/browser/ui/cocoa/electron_menu_controller.mm",
|
"shell/browser/ui/cocoa/electron_menu_controller.mm",
|
||||||
"shell/browser/ui/cocoa/electron_native_widget_mac.h",
|
"shell/browser/ui/cocoa/electron_native_widget_mac.h",
|
||||||
|
@ -187,6 +191,8 @@ filenames = {
|
||||||
"shell/browser/ui/cocoa/window_buttons_proxy.mm",
|
"shell/browser/ui/cocoa/window_buttons_proxy.mm",
|
||||||
"shell/browser/ui/drag_util_mac.mm",
|
"shell/browser/ui/drag_util_mac.mm",
|
||||||
"shell/browser/ui/file_dialog_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/message_box_mac.mm",
|
||||||
"shell/browser/ui/tray_icon_cocoa.h",
|
"shell/browser/ui/tray_icon_cocoa.h",
|
||||||
"shell/browser/ui/tray_icon_cocoa.mm",
|
"shell/browser/ui/tray_icon_cocoa.mm",
|
||||||
|
@ -202,7 +208,6 @@ filenames = {
|
||||||
"shell/common/node_bindings_mac.cc",
|
"shell/common/node_bindings_mac.cc",
|
||||||
"shell/common/node_bindings_mac.h",
|
"shell/common/node_bindings_mac.h",
|
||||||
"shell/common/platform_util_mac.mm",
|
"shell/common/platform_util_mac.mm",
|
||||||
"shell/browser/ui/views/inspectable_web_contents_view_mac.mm",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
lib_sources_views = [
|
lib_sources_views = [
|
||||||
|
@ -217,6 +222,8 @@ filenames = {
|
||||||
"shell/browser/ui/views/electron_views_delegate.h",
|
"shell/browser/ui/views/electron_views_delegate.h",
|
||||||
"shell/browser/ui/views/frameless_view.cc",
|
"shell/browser/ui/views/frameless_view.cc",
|
||||||
"shell/browser/ui/views/frameless_view.h",
|
"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.cc",
|
||||||
"shell/browser/ui/views/menu_bar.h",
|
"shell/browser/ui/views/menu_bar.h",
|
||||||
"shell/browser/ui/views/menu_delegate.cc",
|
"shell/browser/ui/views/menu_delegate.cc",
|
||||||
|
|
|
@ -121,6 +121,11 @@ BaseWindow::BaseWindow(gin_helper::Arguments* args,
|
||||||
BaseWindow::~BaseWindow() {
|
BaseWindow::~BaseWindow() {
|
||||||
CloseImmediately();
|
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.
|
// Remove global reference so the JS object can be garbage collected.
|
||||||
self_ref_.Reset();
|
self_ref_.Reset();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,14 +26,29 @@
|
||||||
#include "ui/views/view_class_properties.h"
|
#include "ui/views/view_class_properties.h"
|
||||||
#include "ui/views/widget/widget.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 {
|
namespace electron::api {
|
||||||
|
|
||||||
WebContentsView::WebContentsView(v8::Isolate* isolate,
|
WebContentsView::WebContentsView(v8::Isolate* isolate,
|
||||||
gin::Handle<WebContents> web_contents)
|
gin::Handle<WebContents> web_contents)
|
||||||
: View(web_contents->inspectable_web_contents()->GetView()),
|
#if BUILDFLAG(IS_MAC)
|
||||||
|
: View(new DelayedNativeViewHost(web_contents->inspectable_web_contents()
|
||||||
|
->GetView()
|
||||||
|
->GetNativeView())),
|
||||||
|
#else
|
||||||
|
: View(web_contents->inspectable_web_contents()->GetView()->GetView()),
|
||||||
|
#endif
|
||||||
web_contents_(isolate, web_contents.ToV8()),
|
web_contents_(isolate, web_contents.ToV8()),
|
||||||
api_web_contents_(web_contents.get()) {
|
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);
|
set_delete_view(false);
|
||||||
|
#endif
|
||||||
view()->SetProperty(
|
view()->SetProperty(
|
||||||
views::kFlexBehaviorKey,
|
views::kFlexBehaviorKey,
|
||||||
views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToMinimum,
|
views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToMinimum,
|
||||||
|
@ -74,15 +89,8 @@ void WebContentsView::SetBorderRadius(int radius) {
|
||||||
|
|
||||||
void WebContentsView::ApplyBorderRadius() {
|
void WebContentsView::ApplyBorderRadius() {
|
||||||
if (border_radius().has_value() && api_web_contents_ && view()->GetWidget()) {
|
if (border_radius().has_value() && api_web_contents_ && view()->GetWidget()) {
|
||||||
auto* web_view = api_web_contents_->inspectable_web_contents()
|
auto* view = api_web_contents_->inspectable_web_contents()->GetView();
|
||||||
->GetView()
|
view->SetCornerRadii(gfx::RoundedCornersF(border_radius().value()));
|
||||||
->contents_web_view();
|
|
||||||
|
|
||||||
// WebView won't exist for offscreen rendering.
|
|
||||||
if (web_view) {
|
|
||||||
web_view->holder()->SetCornerRadii(
|
|
||||||
gfx::RoundedCornersF(border_radius().value()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -236,7 +236,7 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
|
||||||
views::Widget::InitParams::TYPE_WINDOW);
|
views::Widget::InitParams::TYPE_WINDOW);
|
||||||
params.bounds = bounds;
|
params.bounds = bounds;
|
||||||
params.delegate = this;
|
params.delegate = this;
|
||||||
params.headless_mode = true;
|
params.type = views::Widget::InitParams::TYPE_WINDOW;
|
||||||
params.native_widget =
|
params.native_widget =
|
||||||
new ElectronNativeWidgetMac(this, windowType, styleMask, widget());
|
new ElectronNativeWidgetMac(this, windowType, styleMask, widget());
|
||||||
widget()->Init(std::move(params));
|
widget()->Init(std::move(params));
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "content/public/common/color_parser.h"
|
#include "content/public/common/color_parser.h"
|
||||||
#include "shell/browser/api/electron_api_web_contents.h"
|
#include "shell/browser/api/electron_api_web_contents.h"
|
||||||
#include "shell/browser/ui/inspectable_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/views/root_view.h"
|
#include "shell/browser/ui/views/root_view.h"
|
||||||
#include "shell/browser/web_contents_preferences.h"
|
#include "shell/browser/web_contents_preferences.h"
|
||||||
#include "shell/browser/web_view_manager.h"
|
#include "shell/browser/web_view_manager.h"
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
// 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_
|
|
@ -0,0 +1,44 @@
|
||||||
|
// 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
|
|
@ -0,0 +1,56 @@
|
||||||
|
// 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 <AppKit/AppKit.h>
|
||||||
|
|
||||||
|
#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 <NSWindowDelegate> {
|
||||||
|
@private
|
||||||
|
raw_ptr<electron::InspectableWebContentsViewMac> 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)setCornerRadii:(CGFloat)cornerRadius;
|
||||||
|
- (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_
|
|
@ -0,0 +1,352 @@
|
||||||
|
// 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)setCornerRadii:(CGFloat)cornerRadius {
|
||||||
|
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();
|
||||||
|
webContentsView.wantsLayer = YES;
|
||||||
|
webContentsView.layer.cornerRadius = cornerRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (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
|
|
@ -200,11 +200,6 @@ void SwizzleSwipeWithEvent(NSView* view, SEL swiz_selector) {
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen*)screen {
|
- (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.
|
// Resizing is disabled.
|
||||||
if (electron::ScopedDisableResize::IsResizeDisabled())
|
if (electron::ScopedDisableResize::IsResizeDisabled())
|
||||||
return [self frame];
|
return [self frame];
|
||||||
|
|
|
@ -297,6 +297,11 @@ class InspectableWebContents::NetworkResourceLoader
|
||||||
base::TimeDelta retry_delay_;
|
base::TimeDelta retry_delay_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Implemented separately on each platform.
|
||||||
|
InspectableWebContentsView* CreateInspectableContentsView(
|
||||||
|
InspectableWebContents* inspectable_web_contents);
|
||||||
|
|
||||||
|
// static
|
||||||
// static
|
// static
|
||||||
void InspectableWebContents::RegisterPrefs(PrefRegistrySimple* registry) {
|
void InspectableWebContents::RegisterPrefs(PrefRegistrySimple* registry) {
|
||||||
registry->RegisterDictionaryPref(kDevToolsBoundsPref,
|
registry->RegisterDictionaryPref(kDevToolsBoundsPref,
|
||||||
|
@ -312,7 +317,7 @@ InspectableWebContents::InspectableWebContents(
|
||||||
: pref_service_(pref_service),
|
: pref_service_(pref_service),
|
||||||
web_contents_(std::move(web_contents)),
|
web_contents_(std::move(web_contents)),
|
||||||
is_guest_(is_guest),
|
is_guest_(is_guest),
|
||||||
view_(new InspectableWebContentsView(this)) {
|
view_(CreateInspectableContentsView(this)) {
|
||||||
const base::Value* bounds_dict =
|
const base::Value* bounds_dict =
|
||||||
&pref_service_->GetValue(kDevToolsBoundsPref);
|
&pref_service_->GetValue(kDevToolsBoundsPref);
|
||||||
if (bounds_dict->is_dict()) {
|
if (bounds_dict->is_dict()) {
|
||||||
|
|
|
@ -5,234 +5,12 @@
|
||||||
|
|
||||||
#include "shell/browser/ui/inspectable_web_contents_view.h"
|
#include "shell/browser/ui/inspectable_web_contents_view.h"
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include "base/memory/raw_ptr.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 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<InspectableWebContentsView> shell_;
|
|
||||||
raw_ptr<views::View> view_;
|
|
||||||
raw_ptr<views::Widget> widget_;
|
|
||||||
ui::ImageModel icon_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
InspectableWebContentsView::InspectableWebContentsView(
|
InspectableWebContentsView::InspectableWebContentsView(
|
||||||
InspectableWebContents* inspectable_web_contents)
|
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_view_ = contents_web_view_ = contents_web_view;
|
|
||||||
} else {
|
|
||||||
contents_view_ = new views::Label(u"No content under offscreen mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
devtools_web_view_->SetVisible(false);
|
InspectableWebContentsView::~InspectableWebContentsView() = default;
|
||||||
AddChildView(devtools_web_view_.get());
|
|
||||||
AddChildView(contents_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<views::Widget>();
|
|
||||||
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{
|
|
||||||
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_view_->SetBoundsRect(GetContentsBounds());
|
|
||||||
// Propagate layout call to all children, for example browser views.
|
|
||||||
LayoutSuperclass<View>(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_view_->SetBoundsRect(new_contents_bounds);
|
|
||||||
|
|
||||||
// Propagate layout call to all children, for example browser views.
|
|
||||||
LayoutSuperclass<View>(this);
|
|
||||||
|
|
||||||
if (GetDelegate())
|
|
||||||
GetDelegate()->DevToolsResized();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace electron
|
} // namespace electron
|
||||||
|
|
|
@ -9,74 +9,66 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "base/memory/raw_ptr.h"
|
#include "base/memory/raw_ptr.h"
|
||||||
#include "chrome/browser/devtools/devtools_contents_resizing_strategy.h"
|
|
||||||
#include "electron/shell/common/api/api.mojom.h"
|
#include "electron/shell/common/api/api.mojom.h"
|
||||||
|
#include "ui/gfx/geometry/rounded_corners_f.h"
|
||||||
#include "ui/gfx/native_widget_types.h"
|
#include "ui/gfx/native_widget_types.h"
|
||||||
#include "ui/views/view.h"
|
|
||||||
|
|
||||||
class DevToolsContentsResizingStrategy;
|
class DevToolsContentsResizingStrategy;
|
||||||
|
|
||||||
|
#if defined(TOOLKIT_VIEWS)
|
||||||
namespace views {
|
namespace views {
|
||||||
|
class View;
|
||||||
class WebView;
|
class WebView;
|
||||||
class Widget;
|
|
||||||
class WidgetDelegate;
|
|
||||||
} // namespace views
|
} // namespace views
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace electron {
|
namespace electron {
|
||||||
|
|
||||||
class InspectableWebContents;
|
class InspectableWebContents;
|
||||||
class InspectableWebContentsViewDelegate;
|
class InspectableWebContentsViewDelegate;
|
||||||
|
|
||||||
class InspectableWebContentsView : public views::View {
|
class InspectableWebContentsView {
|
||||||
public:
|
public:
|
||||||
explicit InspectableWebContentsView(
|
explicit InspectableWebContentsView(
|
||||||
InspectableWebContents* inspectable_web_contents);
|
InspectableWebContents* inspectable_web_contents);
|
||||||
~InspectableWebContentsView() override;
|
virtual ~InspectableWebContentsView();
|
||||||
|
|
||||||
InspectableWebContents* inspectable_web_contents() {
|
InspectableWebContents* inspectable_web_contents() {
|
||||||
return inspectable_web_contents_;
|
return inspectable_web_contents_;
|
||||||
}
|
}
|
||||||
|
|
||||||
views::WebView* contents_web_view() const { return contents_web_view_; }
|
|
||||||
|
|
||||||
// The delegate manages its own life.
|
// The delegate manages its own life.
|
||||||
void SetDelegate(InspectableWebContentsViewDelegate* delegate) {
|
void SetDelegate(InspectableWebContentsViewDelegate* delegate) {
|
||||||
delegate_ = delegate;
|
delegate_ = delegate;
|
||||||
}
|
}
|
||||||
InspectableWebContentsViewDelegate* GetDelegate() const { return delegate_; }
|
InspectableWebContentsViewDelegate* GetDelegate() const { return delegate_; }
|
||||||
|
|
||||||
void ShowDevTools(bool activate);
|
#if defined(TOOLKIT_VIEWS) && !BUILDFLAG(IS_MAC)
|
||||||
void CloseDevTools();
|
// Returns the container control, which has devtools view attached.
|
||||||
bool IsDevToolsViewShowing();
|
virtual views::View* GetView() = 0;
|
||||||
bool IsDevToolsViewFocused();
|
#else
|
||||||
void SetIsDocked(bool docked, bool activate);
|
virtual gfx::NativeView GetNativeView() const = 0;
|
||||||
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
|
#endif
|
||||||
|
|
||||||
private:
|
virtual void ShowDevTools(bool activate) = 0;
|
||||||
|
virtual void SetCornerRadii(const gfx::RoundedCornersF& corner_radii) = 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:
|
||||||
// Owns us.
|
// Owns us.
|
||||||
raw_ptr<InspectableWebContents> inspectable_web_contents_;
|
raw_ptr<InspectableWebContents> inspectable_web_contents_;
|
||||||
|
|
||||||
|
private:
|
||||||
raw_ptr<InspectableWebContentsViewDelegate> delegate_ =
|
raw_ptr<InspectableWebContentsViewDelegate> delegate_ =
|
||||||
nullptr; // weak references.
|
nullptr; // weak references.
|
||||||
|
|
||||||
std::unique_ptr<views::Widget> devtools_window_;
|
|
||||||
raw_ptr<views::WebView> devtools_window_web_view_ = nullptr;
|
|
||||||
raw_ptr<views::WebView> devtools_web_view_ = nullptr;
|
|
||||||
raw_ptr<views::WebView> contents_web_view_ = nullptr;
|
|
||||||
raw_ptr<views::View> contents_view_ = nullptr;
|
|
||||||
|
|
||||||
DevToolsContentsResizingStrategy strategy_;
|
|
||||||
bool devtools_visible_ = false;
|
|
||||||
raw_ptr<views::WidgetDelegate> devtools_window_delegate_ = nullptr;
|
|
||||||
std::u16string title_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace electron
|
} // namespace electron
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Copyright (c) 2013 Adam Roben <adam@roben.org>. 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 SetCornerRadii(const gfx::RoundedCornersF& corner_radii) 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_
|
|
@ -0,0 +1,74 @@
|
||||||
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||||
|
// Copyright (c) 2013 Adam Roben <adam@roben.org>. 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::SetCornerRadii(
|
||||||
|
const gfx::RoundedCornersF& corner_radii) {
|
||||||
|
// We can assume all four values are identical.
|
||||||
|
[view_ setCornerRadii:corner_radii.upper_left()];
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
|
@ -1,34 +0,0 @@
|
||||||
// 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
|
|
|
@ -0,0 +1,257 @@
|
||||||
|
// 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 <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#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<InspectableWebContentsViewViews> shell_;
|
||||||
|
raw_ptr<views::View> view_;
|
||||||
|
raw_ptr<views::Widget> 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_view_ = contents_web_view_ = contents_web_view;
|
||||||
|
} else {
|
||||||
|
contents_view_ = new views::Label(u"No content under offscreen mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
devtools_web_view_->SetVisible(false);
|
||||||
|
AddChildView(devtools_web_view_.get());
|
||||||
|
AddChildView(contents_view_.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
InspectableWebContentsViewViews::~InspectableWebContentsViewViews() {
|
||||||
|
if (devtools_window_)
|
||||||
|
inspectable_web_contents()->SaveDevToolsBounds(
|
||||||
|
devtools_window_->GetWindowBoundsInScreen());
|
||||||
|
}
|
||||||
|
|
||||||
|
views::View* InspectableWebContentsViewViews::GetView() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InspectableWebContentsViewViews::SetCornerRadii(
|
||||||
|
const gfx::RoundedCornersF& corner_radii) {
|
||||||
|
// WebView won't exist for offscreen rendering.
|
||||||
|
if (contents_web_view_) {
|
||||||
|
contents_web_view_->holder()->SetCornerRadii(
|
||||||
|
gfx::RoundedCornersF(corner_radii));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<views::Widget>();
|
||||||
|
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{
|
||||||
|
views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET};
|
||||||
|
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_view_->SetBoundsRect(GetContentsBounds());
|
||||||
|
// Propagate layout call to all children, for example browser views.
|
||||||
|
LayoutSuperclass<View>(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_view_->SetBoundsRect(new_contents_bounds);
|
||||||
|
|
||||||
|
// Propagate layout call to all children, for example browser views.
|
||||||
|
LayoutSuperclass<View>(this);
|
||||||
|
|
||||||
|
if (GetDelegate())
|
||||||
|
GetDelegate()->DevToolsResized();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace electron
|
|
@ -0,0 +1,63 @@
|
||||||
|
// 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 <memory>
|
||||||
|
|
||||||
|
#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 SetCornerRadii(const gfx::RoundedCornersF& corner_radii) 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<views::Widget> devtools_window_;
|
||||||
|
raw_ptr<views::WebView> devtools_window_web_view_ = nullptr;
|
||||||
|
raw_ptr<views::WebView> contents_web_view_ = nullptr;
|
||||||
|
raw_ptr<views::View> contents_view_ = nullptr;
|
||||||
|
raw_ptr<views::WebView> devtools_web_view_ = nullptr;
|
||||||
|
|
||||||
|
DevToolsContentsResizingStrategy strategy_;
|
||||||
|
bool devtools_visible_ = false;
|
||||||
|
raw_ptr<views::WidgetDelegate> devtools_window_delegate_ = nullptr;
|
||||||
|
std::u16string title_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace electron
|
||||||
|
|
||||||
|
#endif // ELECTRON_SHELL_BROWSER_UI_VIEWS_INSPECTABLE_WEB_CONTENTS_VIEW_VIEWS_H_
|
Загрузка…
Ссылка в новой задаче