fix: remove InspectableWebContentsViewMac (#43096)
* 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>
* fix: remove custom border radius feat (#42320)
* fix: fix views::Widget::InitParams params
---------
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
This commit is contained in:
parent
b1921b362e
commit
24db198d52
18 changed files with 953 additions and 300 deletions
|
@ -159,8 +159,12 @@ 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,6 +191,8 @@ 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",
|
||||
|
@ -202,7 +208,6 @@ 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 = [
|
||||
|
@ -217,6 +222,8 @@ 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",
|
||||
|
|
|
@ -121,6 +121,11 @@ 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();
|
||||
}
|
||||
|
|
|
@ -24,14 +24,29 @@
|
|||
#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<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()),
|
||||
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,
|
||||
|
|
|
@ -238,7 +238,6 @@ 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));
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#include "content/public/common/color_parser.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_view.h"
|
||||
#include "shell/browser/ui/views/inspectable_web_contents_view_views.h"
|
||||
#include "shell/browser/ui/views/root_view.h"
|
||||
#include "shell/browser/web_contents_preferences.h"
|
||||
#include "shell/browser/web_view_manager.h"
|
||||
|
|
34
shell/browser/ui/cocoa/delayed_native_view_host.h
Normal file
34
shell/browser/ui/cocoa/delayed_native_view_host.h
Normal file
|
@ -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_
|
44
shell/browser/ui/cocoa/delayed_native_view_host.mm
Normal file
44
shell/browser/ui/cocoa/delayed_native_view_host.mm
Normal file
|
@ -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,55 @@
|
|||
// 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)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_
|
340
shell/browser/ui/cocoa/electron_inspectable_web_contents_view.mm
Normal file
340
shell/browser/ui/cocoa/electron_inspectable_web_contents_view.mm
Normal file
|
@ -0,0 +1,340 @@
|
|||
// 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
|
|
@ -200,11 +200,6 @@ 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];
|
||||
|
|
|
@ -300,6 +300,11 @@ 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,
|
||||
|
@ -315,7 +320,7 @@ InspectableWebContents::InspectableWebContents(
|
|||
: pref_service_(pref_service),
|
||||
web_contents_(std::move(web_contents)),
|
||||
is_guest_(is_guest),
|
||||
view_(new InspectableWebContentsView(this)) {
|
||||
view_(CreateInspectableContentsView(this)) {
|
||||
const base::Value* bounds_dict =
|
||||
&pref_service_->GetValue(kDevToolsBoundsPref);
|
||||
if (bounds_dict->is_dict()) {
|
||||
|
|
|
@ -5,235 +5,12 @@
|
|||
|
||||
#include "shell/browser/ui/inspectable_web_contents_view.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(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(
|
||||
InspectableWebContents* 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");
|
||||
}
|
||||
: inspectable_web_contents_(inspectable_web_contents) {}
|
||||
|
||||
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<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;
|
||||
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<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_web_view_->SetBoundsRect(new_contents_bounds);
|
||||
|
||||
// Propagate layout call to all children, for example browser views.
|
||||
LayoutSuperclass<View>(this);
|
||||
|
||||
if (GetDelegate())
|
||||
GetDelegate()->DevToolsResized();
|
||||
}
|
||||
InspectableWebContentsView::~InspectableWebContentsView() = default;
|
||||
|
||||
} // namespace electron
|
||||
|
|
|
@ -9,28 +9,29 @@
|
|||
#include <string>
|
||||
|
||||
#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/geometry/rounded_corners_f.h"
|
||||
#include "ui/gfx/native_widget_types.h"
|
||||
#include "ui/views/view.h"
|
||||
|
||||
class DevToolsContentsResizingStrategy;
|
||||
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
namespace views {
|
||||
class View;
|
||||
class WebView;
|
||||
class Widget;
|
||||
class WidgetDelegate;
|
||||
} // namespace views
|
||||
#endif
|
||||
|
||||
namespace electron {
|
||||
|
||||
class InspectableWebContents;
|
||||
class InspectableWebContentsViewDelegate;
|
||||
|
||||
class InspectableWebContentsView : public views::View {
|
||||
class InspectableWebContentsView {
|
||||
public:
|
||||
explicit InspectableWebContentsView(
|
||||
InspectableWebContents* inspectable_web_contents);
|
||||
~InspectableWebContentsView() override;
|
||||
virtual ~InspectableWebContentsView();
|
||||
|
||||
InspectableWebContents* inspectable_web_contents() {
|
||||
return inspectable_web_contents_;
|
||||
|
@ -42,38 +43,31 @@ class InspectableWebContentsView : public views::View {
|
|||
}
|
||||
InspectableWebContentsViewDelegate* GetDelegate() const { return delegate_; }
|
||||
|
||||
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;
|
||||
#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;
|
||||
#endif
|
||||
|
||||
private:
|
||||
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:
|
||||
// Owns us.
|
||||
raw_ptr<InspectableWebContents> inspectable_web_contents_;
|
||||
|
||||
private:
|
||||
raw_ptr<InspectableWebContentsViewDelegate> delegate_ =
|
||||
nullptr; // weak references.
|
||||
|
||||
std::unique_ptr<views::Widget> devtools_window_;
|
||||
raw_ptr<views::WebView> devtools_window_web_view_ = nullptr;
|
||||
raw_ptr<views::View> contents_web_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
|
||||
|
|
41
shell/browser/ui/inspectable_web_contents_view_mac.h
Normal file
41
shell/browser/ui/inspectable_web_contents_view_mac.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
// 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 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_
|
68
shell/browser/ui/inspectable_web_contents_view_mac.mm
Normal file
68
shell/browser/ui/inspectable_web_contents_view_mac.mm
Normal file
|
@ -0,0 +1,68 @@
|
|||
// 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::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
|
247
shell/browser/ui/views/inspectable_web_contents_view_views.cc
Normal file
247
shell/browser/ui/views/inspectable_web_contents_view_views.cc
Normal file
|
@ -0,0 +1,247 @@
|
|||
// 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_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<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;
|
||||
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<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_web_view_->SetBoundsRect(new_contents_bounds);
|
||||
|
||||
// Propagate layout call to all children, for example browser views.
|
||||
LayoutSuperclass<View>(this);
|
||||
|
||||
if (GetDelegate())
|
||||
GetDelegate()->DevToolsResized();
|
||||
}
|
||||
|
||||
} // namespace electron
|
61
shell/browser/ui/views/inspectable_web_contents_view_views.h
Normal file
61
shell/browser/ui/views/inspectable_web_contents_view_views.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
// 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 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::View> contents_web_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_
|
Loading…
Reference in a new issue