fix: make draggable regions work when devtools is opened on macOS (#26361)

* fix: make draggable region work when devtools is open

* fix: update draggable regions when resizing
This commit is contained in:
Cheng Zhao 2020-11-10 06:54:04 +09:00 committed by GitHub
parent f21a21f172
commit 02a8c0a640
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 78 additions and 20 deletions

View file

@ -63,6 +63,9 @@ class BrowserWindow : public BaseWindow,
void OnActivateContents() override; void OnActivateContents() override;
void OnPageTitleUpdated(const base::string16& title, void OnPageTitleUpdated(const base::string16& title,
bool explicit_set) override; bool explicit_set) override;
#if defined(OS_MAC)
void OnDevToolsResized() override;
#endif
// NativeWindowObserver: // NativeWindowObserver:
void RequestPreferredWidth(int* width) override; void RequestPreferredWidth(int* width) override;

View file

@ -12,27 +12,9 @@
#include "base/mac/scoped_nsobject.h" #include "base/mac/scoped_nsobject.h"
#include "shell/browser/native_browser_view.h" #include "shell/browser/native_browser_view.h"
#include "shell/browser/native_window_mac.h" #include "shell/browser/native_window_mac.h"
#include "shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h"
#include "shell/browser/ui/inspectable_web_contents_view.h" #include "shell/browser/ui/inspectable_web_contents_view.h"
@interface NSView (WebContentsView)
- (void)setMouseDownCanMoveWindow:(BOOL)can_move;
@end
@interface ControlRegionView : NSView
@end
@implementation ControlRegionView
- (BOOL)mouseDownCanMoveWindow {
return NO;
}
- (NSView*)hitTest:(NSPoint)aPoint {
return nil;
}
@end
namespace electron { namespace electron {
namespace api { namespace api {
@ -54,6 +36,10 @@ void BrowserWindow::OverrideNSWindowContentView(InspectableWebContents* iwc) {
[contentView viewDidMoveToWindow]; [contentView viewDidMoveToWindow];
} }
void BrowserWindow::OnDevToolsResized() {
UpdateDraggableRegions(draggable_regions_);
}
void BrowserWindow::UpdateDraggableRegions( void BrowserWindow::UpdateDraggableRegions(
const std::vector<mojom::DraggableRegionPtr>& regions) { const std::vector<mojom::DraggableRegionPtr>& regions) {
if (window_->has_frame()) if (window_->has_frame())

View file

@ -1481,6 +1481,11 @@ void WebContents::DevToolsClosed() {
Emit("devtools-closed"); Emit("devtools-closed");
} }
void WebContents::DevToolsResized() {
for (ExtendedWebContentsObserver& observer : observers_)
observer.OnDevToolsResized();
}
bool WebContents::OnMessageReceived(const IPC::Message& message) { bool WebContents::OnMessageReceived(const IPC::Message& message) {
bool handled = true; bool handled = true;
IPC_BEGIN_MESSAGE_MAP(WebContents, message) IPC_BEGIN_MESSAGE_MAP(WebContents, message)

View file

@ -590,6 +590,7 @@ class WebContents : public gin::Wrappable<WebContents>,
void DevToolsFocused() override; void DevToolsFocused() override;
void DevToolsOpened() override; void DevToolsOpened() override;
void DevToolsClosed() override; void DevToolsClosed() override;
void DevToolsResized() override;
private: private:
ElectronBrowserContext* GetBrowserContext() const; ElectronBrowserContext* GetBrowserContext() const;

View file

@ -25,6 +25,7 @@ class ExtendedWebContentsObserver : public base::CheckedObserver {
virtual void OnActivateContents() {} virtual void OnActivateContents() {}
virtual void OnPageTitleUpdated(const base::string16& title, virtual void OnPageTitleUpdated(const base::string16& title,
bool explicit_set) {} bool explicit_set) {}
virtual void OnDevToolsResized() {}
protected: protected:
~ExtendedWebContentsObserver() override {} ~ExtendedWebContentsObserver() override {}

View file

@ -17,12 +17,20 @@ class InspectableWebContentsViewMac;
using electron::InspectableWebContentsViewMac; using electron::InspectableWebContentsViewMac;
@interface NSView (WebContentsView)
- (void)setMouseDownCanMoveWindow:(BOOL)can_move;
@end
@interface ControlRegionView : NSView
@end
@interface ElectronInspectableWebContentsView : BaseView <NSWindowDelegate> { @interface ElectronInspectableWebContentsView : BaseView <NSWindowDelegate> {
@private @private
electron::InspectableWebContentsViewMac* inspectableWebContentsView_; electron::InspectableWebContentsViewMac* inspectableWebContentsView_;
base::scoped_nsobject<NSView> fake_view_; base::scoped_nsobject<NSView> fake_view_;
base::scoped_nsobject<NSWindow> devtools_window_; base::scoped_nsobject<NSWindow> devtools_window_;
base::scoped_nsobject<ControlRegionView> devtools_mask_;
BOOL devtools_visible_; BOOL devtools_visible_;
BOOL devtools_docked_; BOOL devtools_docked_;
BOOL devtools_is_first_responder_; BOOL devtools_is_first_responder_;

View file

@ -11,6 +11,18 @@
#include "shell/browser/ui/inspectable_web_contents_view_mac.h" #include "shell/browser/ui/inspectable_web_contents_view_mac.h"
#include "ui/gfx/mac/scoped_cocoa_disable_screen_updates.h" #include "ui/gfx/mac/scoped_cocoa_disable_screen_updates.h"
@implementation ControlRegionView
- (BOOL)mouseDownCanMoveWindow {
return NO;
}
- (NSView*)hitTest:(NSPoint)aPoint {
return nil;
}
@end
@implementation ElectronInspectableWebContentsView @implementation ElectronInspectableWebContentsView
- (instancetype)initWithInspectableWebContentsViewMac: - (instancetype)initWithInspectableWebContentsViewMac:
@ -48,6 +60,9 @@
[self addSubview:contentsView]; [self addSubview:contentsView];
} }
// This will float above devtools to exclude it from dragging.
devtools_mask_.reset([[ControlRegionView alloc] initWithFrame:NSZeroRect]);
// See https://code.google.com/p/chromium/issues/detail?id=348490. // See https://code.google.com/p/chromium/issues/detail?id=348490.
[self setWantsLayer:YES]; [self setWantsLayer:YES];
@ -71,6 +86,14 @@
inspectableWebContentsView_->GetDelegate()->DevToolsFocused(); 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 { - (void)setDevToolsVisible:(BOOL)visible activate:(BOOL)activate {
if (visible == devtools_visible_) if (visible == devtools_visible_)
return; return;
@ -84,6 +107,12 @@
devtools_visible_ = visible; devtools_visible_ = visible;
if (devtools_docked_) { if (devtools_docked_) {
if (visible) { if (visible) {
// The devToolsView is placed under the contentsView, so it has to be
// draggable to make draggable region of contentsView work.
[devToolsView setMouseDownCanMoveWindow:YES];
// This view will exclude the actual devtools part from dragging.
[self addSubview:devtools_mask_.get()];
// Place the devToolsView under contentsView, notice that we didn't set // Place the devToolsView under contentsView, notice that we didn't set
// sizes for them until the setContentsResizingStrategy message. // sizes for them until the setContentsResizingStrategy message.
[self addSubview:devToolsView positioned:NSWindowBelow relativeTo:nil]; [self addSubview:devToolsView positioned:NSWindowBelow relativeTo:nil];
@ -94,7 +123,9 @@
} else { } else {
gfx::ScopedCocoaDisableScreenUpdates disabler; gfx::ScopedCocoaDisableScreenUpdates disabler;
[devToolsView removeFromSuperview]; [devToolsView removeFromSuperview];
[devtools_mask_ removeFromSuperview];
[self adjustSubviews]; [self adjustSubviews];
[self notifyDevToolsResized];
} }
} else { } else {
if (visible) { if (visible) {
@ -182,7 +213,7 @@
NSView* devToolsView = [[self subviews] objectAtIndex:0]; NSView* devToolsView = [[self subviews] objectAtIndex:0];
NSView* contentsView = [[self subviews] objectAtIndex:1]; NSView* contentsView = [[self subviews] objectAtIndex:1];
DCHECK_EQ(2u, [[self subviews] count]); DCHECK_EQ(3u, [[self subviews] count]);
gfx::Rect new_devtools_bounds; gfx::Rect new_devtools_bounds;
gfx::Rect new_contents_bounds; gfx::Rect new_contents_bounds;
@ -191,6 +222,28 @@
&new_devtools_bounds, &new_contents_bounds); &new_devtools_bounds, &new_contents_bounds);
[devToolsView setFrame:[self flipRectToNSRect:new_devtools_bounds]]; [devToolsView setFrame:[self flipRectToNSRect:new_devtools_bounds]];
[contentsView setFrame:[self flipRectToNSRect:new_contents_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;
}
[devtools_mask_ setFrame:devtools_frame];
[self notifyDevToolsResized];
} }
- (void)setTitle:(NSString*)title { - (void)setTitle:(NSString*)title {

View file

@ -19,6 +19,7 @@ class InspectableWebContentsViewDelegate {
virtual void DevToolsFocused() {} virtual void DevToolsFocused() {}
virtual void DevToolsOpened() {} virtual void DevToolsOpened() {}
virtual void DevToolsClosed() {} virtual void DevToolsClosed() {}
virtual void DevToolsResized() {}
// Returns the icon of devtools window. // Returns the icon of devtools window.
virtual gfx::ImageSkia GetDevToolsWindowIcon(); virtual gfx::ImageSkia GetDevToolsWindowIcon();