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:
Keeley Hammond 2024-07-30 11:51:51 -07:00 committed by GitHub
parent b1921b362e
commit 24db198d52
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 953 additions and 300 deletions

View file

@ -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",

View file

@ -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();
}

View file

@ -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,

View file

@ -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));

View file

@ -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"

View 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_

View 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

View file

@ -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_

View 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

View file

@ -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];

View file

@ -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()) {

View file

@ -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(&params.wm_class_name,
&params.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

View file

@ -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

View 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_

View 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

View file

@ -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

View 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(&params.wm_class_name,
&params.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

View 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_