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 {
// Clear the touchbar.
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
......@@ -157,12 +162,6 @@ class VIEWS_EXPORT BridgedNativeWidget
// take ownership of |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.
// Return MOVE_LOOP_SUCCESSFUL on mouse up or MOVE_LOOP_CANCELED on premature
// termination via EndMoveLoop() or when window is destroyed during the drag.
......@@ -295,6 +294,8 @@ class VIEWS_EXPORT BridgedNativeWidget
void SetWindowTitle(const base::string16& title) override;
void MakeFirstResponder() override;
void ClearTouchBar() override;
void AcquireCapture() override;
void ReleaseCapture() override;
// TODO(ccameron): This method exists temporarily as we move all direct access
// of TextInputClient out of BridgedContentView.
......@@ -323,6 +324,9 @@ class VIEWS_EXPORT BridgedNativeWidget
// Show the window using -[NSApp beginSheet:..], modal for the parent window.
void ShowAsModalSheet();
// Returns true if capture exists and is currently active.
bool HasCapture();
// CocoaMouseCaptureDelegate:
void PostCapturedEvent(NSEvent* event) override;
void OnMouseCaptureLost() override;
......
......@@ -498,11 +498,13 @@ void BridgedNativeWidget::SetVisibilityState(WindowVisibilityState new_state) {
}
void BridgedNativeWidget::AcquireCapture() {
DCHECK(!HasCapture());
if (HasCapture())
return;
if (!window_visible_)
return; // Capture on hidden windows is disallowed.
mouse_capture_.reset(new CocoaMouseCapture(this));
host_->OnMouseCaptureActiveChanged(true);
// Initiating global event capture with addGlobalMonitorForEventsMatchingMask:
// will reset the mouse cursor to an arrow. Asking the window for an update
......@@ -578,10 +580,10 @@ void BridgedNativeWidget::OnWindowWillClose() {
host_->OnWindowWillClose();
// Ensure BridgedNativeWidget does not have capture, otherwise
// OnMouseCaptureLost() may reference a deleted |native_widget_mac_| when
// called via ~CocoaMouseCapture() upon the destruction of |mouse_capture_|.
// See crbug.com/622201. Also we do this before setting the delegate to nil,
// because this may lead to callbacks to bridge which rely on a valid
// OnMouseCaptureLost() may reference a deleted |host_| when called via
// ~CocoaMouseCapture() upon the destruction of |mouse_capture_|. See
// https://crbug.com/622201. Also we do this before setting the delegate to
// nil, because this may lead to callbacks to bridge which rely on a valid
// delegate.
ReleaseCapture();
......@@ -924,7 +926,7 @@ void BridgedNativeWidget::PostCapturedEvent(NSEvent* event) {
}
void BridgedNativeWidget::OnMouseCaptureLost() {
native_widget_mac_->GetWidget()->OnMouseCaptureLost();
host_->OnMouseCaptureActiveChanged(false);
}
NSWindow* BridgedNativeWidget::GetWindow() const {
......
......@@ -33,6 +33,9 @@ class VIEWS_EXPORT BridgedNativeWidgetHost {
// Indicate if the NSView is the first responder.
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
// not returned.
virtual void OnScrollEvent(const ui::ScrollEvent& const_event) = 0;
......
......@@ -108,6 +108,7 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
bool IsVisible() const { return is_visible_; }
bool IsMiniaturized() const { return is_miniaturized_; }
bool IsWindowKey() const { return is_window_key_; }
bool IsMouseCaptureActive() const { return is_mouse_capture_active_; }
private:
gfx::Vector2d GetBoundsOffsetForParent() const;
......@@ -119,6 +120,7 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
void SetViewSize(const gfx::Size& new_size) override;
void SetKeyboardAccessible(bool enabled) override;
void SetIsFirstResponder(bool is_first_responder) override;
void OnMouseCaptureActiveChanged(bool capture_is_active) override;
void OnScrollEvent(const ui::ScrollEvent& const_event) override;
void OnMouseEvent(const ui::MouseEvent& const_event) override;
void OnGestureEvent(const ui::GestureEvent& const_event) override;
......@@ -190,6 +192,7 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
bool in_fullscreen_transition_ = false;
bool is_miniaturized_ = false;
bool is_window_key_ = false;
bool is_mouse_capture_active_ = false;
gfx::Rect window_bounds_before_fullscreen_;
std::unique_ptr<ui::RecyclableCompositorMac> compositor_;
......
......@@ -277,6 +277,13 @@ void BridgedNativeWidgetHostImpl::SetIsFirstResponder(bool is_first_responder) {
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(
const gfx::Point& location_in_content,
bool* is_draggable_background) {
......
......@@ -14,6 +14,7 @@
#import "ui/base/clipboard/clipboard_util_mac.h"
#include "ui/gfx/image/image_unittest_util.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/view.h"
#include "ui/views/widget/native_widget_mac.h"
......@@ -187,6 +188,8 @@ class DragDropClientMacTest : public WidgetTest {
bridge_ =
NativeWidgetMac::GetBridgeForNativeWindow(widget_->GetNativeWindow());
bridge_host_ = NativeWidgetMac::GetBridgeHostImplForNativeWindow(
widget_->GetNativeWindow());
widget_->Show();
target_ = new DragDropView();
......@@ -205,6 +208,7 @@ class DragDropClientMacTest : public WidgetTest {
protected:
Widget* widget_ = nullptr;
BridgedNativeWidget* bridge_ = nullptr;
BridgedNativeWidgetHostImpl* bridge_host_ = nullptr;
DragDropView* target_ = nullptr;
base::scoped_nsobject<MockDraggingInfo> dragging_info_;
......@@ -236,7 +240,7 @@ TEST_F(DragDropClientMacTest, ReleaseCapture) {
// since the runloop will exit before the system has any opportunity to
// capture anything.
bridge_->AcquireCapture();
EXPECT_TRUE(bridge_->HasCapture());
EXPECT_TRUE(bridge_host_->IsMouseCaptureActive());
// Create the drop data
OSExchangeData data;
......@@ -262,7 +266,7 @@ TEST_F(DragDropClientMacTest, ReleaseCapture) {
target_, data, 0, ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
// 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
......
......@@ -32,6 +32,8 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate {
// Retrieves the bridge associated with the given NSWindow. Returns null if
// the supplied handle has no associated Widget.
static BridgedNativeWidgetHostImpl* GetBridgeHostImplForNativeWindow(
gfx::NativeWindow window);
static BridgedNativeWidget* GetBridgeForNativeWindow(
gfx::NativeWindow window);
......
......@@ -54,6 +54,17 @@ namespace {
base::LazyInstance<ui::GestureRecognizerImplMac>::Leaky
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) {
// If the Widget is modal, it will be displayed as a sheet. This works best if
// it has NSTitledWindowMask. For example, with NSBorderlessWindowMask, the
......@@ -94,12 +105,16 @@ NativeWidgetMac::~NativeWidgetMac() {
// static
BridgedNativeWidget* NativeWidgetMac::GetBridgeForNativeWindow(
gfx::NativeWindow window) {
id<NSWindowDelegate> window_delegate = [window delegate];
if ([window_delegate respondsToSelector:@selector(nativeWidgetMac)]) {
ViewsNSWindowDelegate* delegate =
base::mac::ObjCCastStrict<ViewsNSWindowDelegate>(window_delegate);
return [delegate nativeWidgetMac]->bridge();
}
if (NativeWidgetMac* widget = GetNativeWidgetMacForNativeWindow(window))
return widget->bridge();
return nullptr; // Not created by NativeWidgetMac.
}
// static
BridgedNativeWidgetHostImpl* NativeWidgetMac::GetBridgeHostImplForNativeWindow(
gfx::NativeWindow window) {
if (NativeWidgetMac* widget = GetNativeWidgetMacForNativeWindow(window))
return widget->bridge_host_.get();
return nullptr; // Not created by NativeWidgetMac.
}
......@@ -245,7 +260,7 @@ TooltipManager* NativeWidgetMac::GetTooltipManager() const {
}
void NativeWidgetMac::SetCapture() {
if (bridge() && !bridge()->HasCapture())
if (bridge())
bridge()->AcquireCapture();
}
......@@ -255,7 +270,7 @@ void NativeWidgetMac::ReleaseCapture() {
}
bool NativeWidgetMac::HasCapture() const {
return bridge() && bridge()->HasCapture();
return bridge_host_ && bridge_host_->IsMouseCaptureActive();
}
ui::InputMethod* NativeWidgetMac::GetInputMethod() {
......@@ -734,13 +749,9 @@ NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeView(
// static
NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeWindow(
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];
}
gfx::NativeWindow window) {
if (NativeWidgetMac* widget = GetNativeWidgetMacForNativeWindow(window))
return widget;
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