Files
electron/shell/browser/ui/cocoa/electron_inspectable_web_contents_view.mm
Charles Kerr 523e0d4574 refactor: inline simple getters, pt . 2 (#41254) (#41341)
* refactor: inline AutofillPopup::line_count()

refactor: inline AutofillPopup::value_at()

refactor: inline AutofillPopup::label_at()

* refactor: inline NativeWindow::aspect_ratio()

refactor: inline NativeWindow::aspect_ratio_extra_size()

* refactor: inline BrowserProcessImpl::linux_storage_backend()

* refactor: inline ElectronMenuModel::sharing_item()

* refactor: inline Browser::badge_count()

* refactor: inline WebContents::is_guest()

refactor: inline InspectableWebContents::is_guest()

* refactor: inline InspectableWebContents::dev_tool_bounds()

* refactor: inline WebContents::type()
2024-02-15 11:00:32 -05:00

341 lines
11 KiB
Plaintext

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