Commit b606180d authored by Christopher Cameron's avatar Christopher Cameron Committed by Commit Bot

RemoteMacViews: Separate MouseCapture interface

Add methods mouse capture methods to the BridgedNativeWidgetPublic
interface that BridgedNativeWidget implements.

Have BridgedNativeWidget pass the mouse capture status to
BridgedNativeWidgetHostImpl, which the NativeWidgetMac will access.

Add NativeWidgetMac::GetBridgeHostImplForNativeWindow method for
unittests, and merge the implementations of GetBridgeForNativeWindow,
GetBridgeHostImplForNativeWindow, and GetNativeWidgetForNativeWindow.

Bug: 859152
Change-Id: I25af661ad487b4f5a89bb02b1c655fb0ab27b8fb
Reviewed-on: https://chromium-review.googlesource.com/1186161Reviewed-by: default avatarElly Fong-Jones <ellyjones@chromium.org>
Commit-Queue: ccameron <ccameron@chromium.org>
Cr-Commit-Position: refs/heads/master@{#586392}
parent cc9ef540
...@@ -113,6 +113,11 @@ class VIEWS_EXPORT BridgedNativeWidgetPublic { ...@@ -113,6 +113,11 @@ class VIEWS_EXPORT BridgedNativeWidgetPublic {
// Clear the touchbar. // Clear the touchbar.
virtual void ClearTouchBar() = 0; virtual void ClearTouchBar() = 0;
// Acquiring mouse capture first steals capture from any existing
// CocoaMouseCaptureDelegate, then captures all mouse events until released.
virtual void AcquireCapture() = 0;
virtual void ReleaseCapture() = 0;
}; };
// A bridge to an NSWindow managed by an instance of NativeWidgetMac or // A bridge to an NSWindow managed by an instance of NativeWidgetMac or
...@@ -157,12 +162,6 @@ class VIEWS_EXPORT BridgedNativeWidget ...@@ -157,12 +162,6 @@ class VIEWS_EXPORT BridgedNativeWidget
// take ownership of |view|. // take ownership of |view|.
void SetRootView(views::View* view); void SetRootView(views::View* view);
// Acquiring mouse capture first steals capture from any existing
// CocoaMouseCaptureDelegate, then captures all mouse events until released.
void AcquireCapture();
void ReleaseCapture();
bool HasCapture();
// Start moving the window, pinned to the mouse cursor, and monitor events. // Start moving the window, pinned to the mouse cursor, and monitor events.
// Return MOVE_LOOP_SUCCESSFUL on mouse up or MOVE_LOOP_CANCELED on premature // Return MOVE_LOOP_SUCCESSFUL on mouse up or MOVE_LOOP_CANCELED on premature
// termination via EndMoveLoop() or when window is destroyed during the drag. // termination via EndMoveLoop() or when window is destroyed during the drag.
...@@ -295,6 +294,8 @@ class VIEWS_EXPORT BridgedNativeWidget ...@@ -295,6 +294,8 @@ class VIEWS_EXPORT BridgedNativeWidget
void SetWindowTitle(const base::string16& title) override; void SetWindowTitle(const base::string16& title) override;
void MakeFirstResponder() override; void MakeFirstResponder() override;
void ClearTouchBar() override; void ClearTouchBar() override;
void AcquireCapture() override;
void ReleaseCapture() override;
// TODO(ccameron): This method exists temporarily as we move all direct access // TODO(ccameron): This method exists temporarily as we move all direct access
// of TextInputClient out of BridgedContentView. // of TextInputClient out of BridgedContentView.
...@@ -323,6 +324,9 @@ class VIEWS_EXPORT BridgedNativeWidget ...@@ -323,6 +324,9 @@ class VIEWS_EXPORT BridgedNativeWidget
// Show the window using -[NSApp beginSheet:..], modal for the parent window. // Show the window using -[NSApp beginSheet:..], modal for the parent window.
void ShowAsModalSheet(); void ShowAsModalSheet();
// Returns true if capture exists and is currently active.
bool HasCapture();
// CocoaMouseCaptureDelegate: // CocoaMouseCaptureDelegate:
void PostCapturedEvent(NSEvent* event) override; void PostCapturedEvent(NSEvent* event) override;
void OnMouseCaptureLost() override; void OnMouseCaptureLost() override;
......
...@@ -498,11 +498,13 @@ void BridgedNativeWidget::SetVisibilityState(WindowVisibilityState new_state) { ...@@ -498,11 +498,13 @@ void BridgedNativeWidget::SetVisibilityState(WindowVisibilityState new_state) {
} }
void BridgedNativeWidget::AcquireCapture() { void BridgedNativeWidget::AcquireCapture() {
DCHECK(!HasCapture()); if (HasCapture())
return;
if (!window_visible_) if (!window_visible_)
return; // Capture on hidden windows is disallowed. return; // Capture on hidden windows is disallowed.
mouse_capture_.reset(new CocoaMouseCapture(this)); mouse_capture_.reset(new CocoaMouseCapture(this));
host_->OnMouseCaptureActiveChanged(true);
// Initiating global event capture with addGlobalMonitorForEventsMatchingMask: // Initiating global event capture with addGlobalMonitorForEventsMatchingMask:
// will reset the mouse cursor to an arrow. Asking the window for an update // will reset the mouse cursor to an arrow. Asking the window for an update
...@@ -578,10 +580,10 @@ void BridgedNativeWidget::OnWindowWillClose() { ...@@ -578,10 +580,10 @@ void BridgedNativeWidget::OnWindowWillClose() {
host_->OnWindowWillClose(); host_->OnWindowWillClose();
// Ensure BridgedNativeWidget does not have capture, otherwise // Ensure BridgedNativeWidget does not have capture, otherwise
// OnMouseCaptureLost() may reference a deleted |native_widget_mac_| when // OnMouseCaptureLost() may reference a deleted |host_| when called via
// called via ~CocoaMouseCapture() upon the destruction of |mouse_capture_|. // ~CocoaMouseCapture() upon the destruction of |mouse_capture_|. See
// See crbug.com/622201. Also we do this before setting the delegate to nil, // https://crbug.com/622201. Also we do this before setting the delegate to
// because this may lead to callbacks to bridge which rely on a valid // nil, because this may lead to callbacks to bridge which rely on a valid
// delegate. // delegate.
ReleaseCapture(); ReleaseCapture();
...@@ -924,7 +926,7 @@ void BridgedNativeWidget::PostCapturedEvent(NSEvent* event) { ...@@ -924,7 +926,7 @@ void BridgedNativeWidget::PostCapturedEvent(NSEvent* event) {
} }
void BridgedNativeWidget::OnMouseCaptureLost() { void BridgedNativeWidget::OnMouseCaptureLost() {
native_widget_mac_->GetWidget()->OnMouseCaptureLost(); host_->OnMouseCaptureActiveChanged(false);
} }
NSWindow* BridgedNativeWidget::GetWindow() const { NSWindow* BridgedNativeWidget::GetWindow() const {
......
...@@ -33,6 +33,9 @@ class VIEWS_EXPORT BridgedNativeWidgetHost { ...@@ -33,6 +33,9 @@ class VIEWS_EXPORT BridgedNativeWidgetHost {
// Indicate if the NSView is the first responder. // Indicate if the NSView is the first responder.
virtual void SetIsFirstResponder(bool is_first_responder) = 0; virtual void SetIsFirstResponder(bool is_first_responder) = 0;
// Indicate if mouse capture is active.
virtual void OnMouseCaptureActiveChanged(bool capture_is_active) = 0;
// Handle events. Note that whether or not the event is actually handled is // Handle events. Note that whether or not the event is actually handled is
// not returned. // not returned.
virtual void OnScrollEvent(const ui::ScrollEvent& const_event) = 0; virtual void OnScrollEvent(const ui::ScrollEvent& const_event) = 0;
......
...@@ -108,6 +108,7 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl ...@@ -108,6 +108,7 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
bool IsVisible() const { return is_visible_; } bool IsVisible() const { return is_visible_; }
bool IsMiniaturized() const { return is_miniaturized_; } bool IsMiniaturized() const { return is_miniaturized_; }
bool IsWindowKey() const { return is_window_key_; } bool IsWindowKey() const { return is_window_key_; }
bool IsMouseCaptureActive() const { return is_mouse_capture_active_; }
private: private:
gfx::Vector2d GetBoundsOffsetForParent() const; gfx::Vector2d GetBoundsOffsetForParent() const;
...@@ -119,6 +120,7 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl ...@@ -119,6 +120,7 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
void SetViewSize(const gfx::Size& new_size) override; void SetViewSize(const gfx::Size& new_size) override;
void SetKeyboardAccessible(bool enabled) override; void SetKeyboardAccessible(bool enabled) override;
void SetIsFirstResponder(bool is_first_responder) override; void SetIsFirstResponder(bool is_first_responder) override;
void OnMouseCaptureActiveChanged(bool capture_is_active) override;
void OnScrollEvent(const ui::ScrollEvent& const_event) override; void OnScrollEvent(const ui::ScrollEvent& const_event) override;
void OnMouseEvent(const ui::MouseEvent& const_event) override; void OnMouseEvent(const ui::MouseEvent& const_event) override;
void OnGestureEvent(const ui::GestureEvent& const_event) override; void OnGestureEvent(const ui::GestureEvent& const_event) override;
...@@ -190,6 +192,7 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl ...@@ -190,6 +192,7 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
bool in_fullscreen_transition_ = false; bool in_fullscreen_transition_ = false;
bool is_miniaturized_ = false; bool is_miniaturized_ = false;
bool is_window_key_ = false; bool is_window_key_ = false;
bool is_mouse_capture_active_ = false;
gfx::Rect window_bounds_before_fullscreen_; gfx::Rect window_bounds_before_fullscreen_;
std::unique_ptr<ui::RecyclableCompositorMac> compositor_; std::unique_ptr<ui::RecyclableCompositorMac> compositor_;
......
...@@ -277,6 +277,13 @@ void BridgedNativeWidgetHostImpl::SetIsFirstResponder(bool is_first_responder) { ...@@ -277,6 +277,13 @@ void BridgedNativeWidgetHostImpl::SetIsFirstResponder(bool is_first_responder) {
root_view_->GetWidget()->GetFocusManager()->StoreFocusedView(true); root_view_->GetWidget()->GetFocusManager()->StoreFocusedView(true);
} }
void BridgedNativeWidgetHostImpl::OnMouseCaptureActiveChanged(bool is_active) {
DCHECK_NE(is_mouse_capture_active_, is_active);
is_mouse_capture_active_ = is_active;
if (!is_mouse_capture_active_)
native_widget_mac_->GetWidget()->OnMouseCaptureLost();
}
void BridgedNativeWidgetHostImpl::GetIsDraggableBackgroundAt( void BridgedNativeWidgetHostImpl::GetIsDraggableBackgroundAt(
const gfx::Point& location_in_content, const gfx::Point& location_in_content,
bool* is_draggable_background) { bool* is_draggable_background) {
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#import "ui/base/clipboard/clipboard_util_mac.h" #import "ui/base/clipboard/clipboard_util_mac.h"
#include "ui/gfx/image/image_unittest_util.h" #include "ui/gfx/image/image_unittest_util.h"
#import "ui/views/cocoa/bridged_native_widget.h" #import "ui/views/cocoa/bridged_native_widget.h"
#import "ui/views/cocoa/bridged_native_widget_host_impl.h"
#include "ui/views/test/widget_test.h" #include "ui/views/test/widget_test.h"
#include "ui/views/view.h" #include "ui/views/view.h"
#include "ui/views/widget/native_widget_mac.h" #include "ui/views/widget/native_widget_mac.h"
...@@ -187,6 +188,8 @@ class DragDropClientMacTest : public WidgetTest { ...@@ -187,6 +188,8 @@ class DragDropClientMacTest : public WidgetTest {
bridge_ = bridge_ =
NativeWidgetMac::GetBridgeForNativeWindow(widget_->GetNativeWindow()); NativeWidgetMac::GetBridgeForNativeWindow(widget_->GetNativeWindow());
bridge_host_ = NativeWidgetMac::GetBridgeHostImplForNativeWindow(
widget_->GetNativeWindow());
widget_->Show(); widget_->Show();
target_ = new DragDropView(); target_ = new DragDropView();
...@@ -205,6 +208,7 @@ class DragDropClientMacTest : public WidgetTest { ...@@ -205,6 +208,7 @@ class DragDropClientMacTest : public WidgetTest {
protected: protected:
Widget* widget_ = nullptr; Widget* widget_ = nullptr;
BridgedNativeWidget* bridge_ = nullptr; BridgedNativeWidget* bridge_ = nullptr;
BridgedNativeWidgetHostImpl* bridge_host_ = nullptr;
DragDropView* target_ = nullptr; DragDropView* target_ = nullptr;
base::scoped_nsobject<MockDraggingInfo> dragging_info_; base::scoped_nsobject<MockDraggingInfo> dragging_info_;
...@@ -236,7 +240,7 @@ TEST_F(DragDropClientMacTest, ReleaseCapture) { ...@@ -236,7 +240,7 @@ TEST_F(DragDropClientMacTest, ReleaseCapture) {
// since the runloop will exit before the system has any opportunity to // since the runloop will exit before the system has any opportunity to
// capture anything. // capture anything.
bridge_->AcquireCapture(); bridge_->AcquireCapture();
EXPECT_TRUE(bridge_->HasCapture()); EXPECT_TRUE(bridge_host_->IsMouseCaptureActive());
// Create the drop data // Create the drop data
OSExchangeData data; OSExchangeData data;
...@@ -262,7 +266,7 @@ TEST_F(DragDropClientMacTest, ReleaseCapture) { ...@@ -262,7 +266,7 @@ TEST_F(DragDropClientMacTest, ReleaseCapture) {
target_, data, 0, ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE); target_, data, 0, ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
// The capture should be released. // The capture should be released.
EXPECT_FALSE(bridge_->HasCapture()); EXPECT_FALSE(bridge_host_->IsMouseCaptureActive());
} }
// Tests if the drag and drop target rejects the dropped data with the // Tests if the drag and drop target rejects the dropped data with the
......
...@@ -32,6 +32,8 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate { ...@@ -32,6 +32,8 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate {
// Retrieves the bridge associated with the given NSWindow. Returns null if // Retrieves the bridge associated with the given NSWindow. Returns null if
// the supplied handle has no associated Widget. // the supplied handle has no associated Widget.
static BridgedNativeWidgetHostImpl* GetBridgeHostImplForNativeWindow(
gfx::NativeWindow window);
static BridgedNativeWidget* GetBridgeForNativeWindow( static BridgedNativeWidget* GetBridgeForNativeWindow(
gfx::NativeWindow window); gfx::NativeWindow window);
......
...@@ -54,6 +54,17 @@ namespace { ...@@ -54,6 +54,17 @@ namespace {
base::LazyInstance<ui::GestureRecognizerImplMac>::Leaky base::LazyInstance<ui::GestureRecognizerImplMac>::Leaky
g_gesture_recognizer_instance = LAZY_INSTANCE_INITIALIZER; g_gesture_recognizer_instance = LAZY_INSTANCE_INITIALIZER;
NativeWidgetMac* GetNativeWidgetMacForNativeWindow(
gfx::NativeWindow native_window) {
id<NSWindowDelegate> window_delegate = [native_window delegate];
if ([window_delegate respondsToSelector:@selector(nativeWidgetMac)]) {
ViewsNSWindowDelegate* delegate =
base::mac::ObjCCastStrict<ViewsNSWindowDelegate>(window_delegate);
return [delegate nativeWidgetMac];
}
return nullptr; // Not created by NativeWidgetMac.
}
NSInteger StyleMaskForParams(const Widget::InitParams& params) { NSInteger StyleMaskForParams(const Widget::InitParams& params) {
// If the Widget is modal, it will be displayed as a sheet. This works best if // If the Widget is modal, it will be displayed as a sheet. This works best if
// it has NSTitledWindowMask. For example, with NSBorderlessWindowMask, the // it has NSTitledWindowMask. For example, with NSBorderlessWindowMask, the
...@@ -94,12 +105,16 @@ NativeWidgetMac::~NativeWidgetMac() { ...@@ -94,12 +105,16 @@ NativeWidgetMac::~NativeWidgetMac() {
// static // static
BridgedNativeWidget* NativeWidgetMac::GetBridgeForNativeWindow( BridgedNativeWidget* NativeWidgetMac::GetBridgeForNativeWindow(
gfx::NativeWindow window) { gfx::NativeWindow window) {
id<NSWindowDelegate> window_delegate = [window delegate]; if (NativeWidgetMac* widget = GetNativeWidgetMacForNativeWindow(window))
if ([window_delegate respondsToSelector:@selector(nativeWidgetMac)]) { return widget->bridge();
ViewsNSWindowDelegate* delegate = return nullptr; // Not created by NativeWidgetMac.
base::mac::ObjCCastStrict<ViewsNSWindowDelegate>(window_delegate); }
return [delegate nativeWidgetMac]->bridge();
} // static
BridgedNativeWidgetHostImpl* NativeWidgetMac::GetBridgeHostImplForNativeWindow(
gfx::NativeWindow window) {
if (NativeWidgetMac* widget = GetNativeWidgetMacForNativeWindow(window))
return widget->bridge_host_.get();
return nullptr; // Not created by NativeWidgetMac. return nullptr; // Not created by NativeWidgetMac.
} }
...@@ -245,7 +260,7 @@ TooltipManager* NativeWidgetMac::GetTooltipManager() const { ...@@ -245,7 +260,7 @@ TooltipManager* NativeWidgetMac::GetTooltipManager() const {
} }
void NativeWidgetMac::SetCapture() { void NativeWidgetMac::SetCapture() {
if (bridge() && !bridge()->HasCapture()) if (bridge())
bridge()->AcquireCapture(); bridge()->AcquireCapture();
} }
...@@ -255,7 +270,7 @@ void NativeWidgetMac::ReleaseCapture() { ...@@ -255,7 +270,7 @@ void NativeWidgetMac::ReleaseCapture() {
} }
bool NativeWidgetMac::HasCapture() const { bool NativeWidgetMac::HasCapture() const {
return bridge() && bridge()->HasCapture(); return bridge_host_ && bridge_host_->IsMouseCaptureActive();
} }
ui::InputMethod* NativeWidgetMac::GetInputMethod() { ui::InputMethod* NativeWidgetMac::GetInputMethod() {
...@@ -734,13 +749,9 @@ NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeView( ...@@ -734,13 +749,9 @@ NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeView(
// static // static
NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeWindow( NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeWindow(
gfx::NativeWindow native_window) { gfx::NativeWindow window) {
id<NSWindowDelegate> window_delegate = [native_window delegate]; if (NativeWidgetMac* widget = GetNativeWidgetMacForNativeWindow(window))
if ([window_delegate respondsToSelector:@selector(nativeWidgetMac)]) { return widget;
ViewsNSWindowDelegate* delegate =
base::mac::ObjCCastStrict<ViewsNSWindowDelegate>(window_delegate);
return [delegate nativeWidgetMac];
}
return nullptr; // Not created by NativeWidgetMac. return nullptr; // Not created by NativeWidgetMac.
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment