Chromium Code Reviews| Index: ui/views/cocoa/bridged_native_widget_interactive_uitest.mm |
| diff --git a/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm b/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm |
| index b0962fb9a27116e7ee142f1f5933445a873b23ff..0e483ca984c87e9b1bb7350d6cb77225acb32645 100644 |
| --- a/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm |
| +++ b/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm |
| @@ -9,9 +9,14 @@ |
| #import "base/mac/mac_util.h" |
| #import "base/mac/sdk_forward_declarations.h" |
| #import "ui/base/test/nswindow_fullscreen_notification_waiter.h" |
| +#include "ui/base/hit_test.h" |
| +#import "ui/base/test/windowed_nsnotification_observer.h" |
| +#include "ui/events/test/cocoa_test_event_utils.h" |
|
tapted
2015/06/03 07:04:50
nit: import
jackhou1
2015/06/03 08:13:53
Done.
|
| #include "ui/views/test/widget_test.h" |
| +#include "ui/views/window/native_frame_view.h" |
| namespace views { |
| +namespace test { |
| class BridgedNativeWidgetUITest : public test::WidgetTest { |
| public: |
| @@ -144,4 +149,182 @@ TEST_F(BridgedNativeWidgetUITest, FullscreenEnterAndExit) { |
| EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds()); |
| } |
| +namespace { |
| + |
| +// This is used to wait for reposted events to be seen. We can't just use |
| +// RunPendingMessages() because CGEventPost might not be synchronous. |
| +class HitTestBridgedNativeWidget : public BridgedNativeWidget { |
| + public: |
| + HitTestBridgedNativeWidget(NativeWidgetMac* widget) |
|
tapted
2015/06/03 07:04:50
nit:explicit
jackhou1
2015/06/03 08:13:53
Done.
|
| + : BridgedNativeWidget(widget) {} |
| + |
| + bool ShouldRepostPendingLeftMouseDown(NSPoint location_in_window) override { |
|
tapted
2015/06/03 07:04:50
nit: // BridgedNativeWidget:
jackhou1
2015/06/03 08:13:52
Done.
|
| + bool draggable_before = [ns_view() mouseDownCanMoveWindow]; |
| + bool should_repost = BridgedNativeWidget::ShouldRepostPendingLeftMouseDown( |
| + location_in_window); |
| + bool draggable_after = [ns_view() mouseDownCanMoveWindow]; |
| + |
| + if (run_loop_.get() && draggable_before && !draggable_after) |
| + run_loop_->Quit(); |
| + |
| + return should_repost; |
| + } |
| + |
| + void WaitForRepost() { |
|
tapted
2015/06/03 07:04:50
maybe WaitForIsDraggableChange?
jackhou1
2015/06/03 08:13:52
Done.
|
| + run_loop_.reset(new base::RunLoop); |
|
tapted
2015/06/03 07:04:50
Same trick with a RunLoop on the stack?
jackhou1
2015/06/03 08:13:53
Done.
|
| + run_loop_->Run(); |
| + } |
| + |
| + private: |
| + scoped_ptr<base::RunLoop> run_loop_; |
| +}; |
|
tapted
2015/06/03 07:04:50
nit: DISALLOW(..
jackhou1
2015/06/03 08:13:53
Done.
|
| + |
| +// This is used to return a customized result to NonClientHitTest. |
| +class HitTestNonClientFrameView : public NativeFrameView { |
| + public: |
| + HitTestNonClientFrameView(Widget* widget) |
|
tapted
2015/06/03 07:04:50
nit: explciit
jackhou1
2015/06/03 08:13:52
Done.
|
| + : NativeFrameView(widget), hit_test_result_(HTNOWHERE) {} |
| + |
| + // NonClientFrameView overrides: |
| + int NonClientHitTest(const gfx::Point& point) override { |
| + return hit_test_result_; |
| + } |
| + |
| + void set_hit_test_result(int component) { hit_test_result_ = component; } |
| + |
| + private: |
| + int hit_test_result_; |
| +}; |
|
tapted
2015/06/03 07:04:50
nit: DISALLOW_COPY_..
jackhou1
2015/06/03 08:13:52
Done.
|
| + |
| +void WaitForEvent(NSUInteger mask) { |
| + // Pointer because the handler block captures local variables by copying. |
| + base::RunLoop* run_loop = new base::RunLoop(); |
| + id monitor = [NSEvent |
| + addLocalMonitorForEventsMatchingMask:mask |
| + handler:^NSEvent*(NSEvent* ns_event) { |
| + run_loop->Quit(); |
| + return ns_event; |
| + }]; |
| + run_loop->Run(); |
| + [NSEvent removeMonitor:monitor]; |
| + delete run_loop; |
| +} |
| + |
| +} // namespace |
| + |
| +// This is used to inject test versions of NativeFrameView and |
| +// BridgedNativeWidget. |
| +class HitTestNativeWidgetMac : public NativeWidgetMac { |
| + public: |
| + HitTestNativeWidgetMac(internal::NativeWidgetDelegate* delegate, |
| + NativeFrameView* native_frame_view) |
| + : NativeWidgetMac(delegate), native_frame_view_(native_frame_view) { |
| + NativeWidgetMac::bridge_.reset(new HitTestBridgedNativeWidget(this)); |
| + } |
| + |
| + HitTestBridgedNativeWidget* bridge() { |
| + return static_cast<HitTestBridgedNativeWidget*>( |
| + NativeWidgetMac::bridge_.get()); |
| + } |
| + |
| + // internal::NativeWidgetPrivate: |
| + NonClientFrameView* CreateNonClientFrameView() override { |
| + return native_frame_view_; |
| + } |
| + |
| + private: |
| + // Owned by Widget. |
| + NativeFrameView* native_frame_view_; |
| +}; |
|
tapted
2015/06/03 07:04:50
nit: DISALLOW_COPY.. (one of these comments is re
jackhou1
2015/06/03 08:13:53
Done.
|
| + |
| +TEST_F(BridgedNativeWidgetUITest, HitTest) { |
| + Widget widget; |
| + HitTestNonClientFrameView* frame_view = |
| + new HitTestNonClientFrameView(&widget); |
| + test::HitTestNativeWidgetMac* native_widget = |
| + new test::HitTestNativeWidgetMac(&widget, frame_view); |
| + Widget::InitParams init_params = |
| + CreateParams(Widget::InitParams::TYPE_WINDOW); |
| + init_params.native_widget = native_widget; |
| + init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| + init_params.bounds = gfx::Rect(100, 200, 400, 300); |
| + widget.Init(init_params); |
| + widget.Show(); |
| + RunPendingMessages(); |
| + |
| + // Dragging the window should work. |
| + frame_view->set_hit_test_result(HTCAPTION); |
| + { |
| + EXPECT_EQ(100, [widget.GetNativeWindow() frame].origin.x); |
| + |
| + NSEvent* mouse_down = cocoa_test_event_utils::LeftMouseDownAtPointInWindow( |
| + NSMakePoint(10, 10), widget.GetNativeWindow()); |
| + CGEventPost(kCGSessionEventTap, [mouse_down CGEvent]); |
| + native_widget->bridge()->WaitForRepost(); |
| + |
| + base::scoped_nsobject<WindowedNSNotificationObserver> ns_observer( |
| + [[WindowedNSNotificationObserver alloc] |
| + initForNotification:NSWindowDidMoveNotification]); |
| + NSEvent* mouse_drag = cocoa_test_event_utils::MouseEventAtPointInWindow( |
| + NSMakePoint(110, 110), NSLeftMouseDragged, widget.GetNativeWindow(), 0); |
| + CGEventPost(kCGSessionEventTap, [mouse_drag CGEvent]); |
| + [ns_observer wait]; |
| + EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x); |
| + |
| + NSEvent* mouse_up = cocoa_test_event_utils::MouseEventAtPointInWindow( |
| + NSMakePoint(10, 10), NSLeftMouseUp, widget.GetNativeWindow(), 0); |
| + CGEventPost(kCGSessionEventTap, [mouse_up CGEvent]); |
| + WaitForEvent(NSLeftMouseUpMask); |
| + EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x); |
| + } |
| + |
| + // Mouse-downs on the window controls should not be intercepted. |
| + { |
| + EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x); |
| + |
| + base::scoped_nsobject<WindowedNSNotificationObserver> ns_observer( |
| + [[WindowedNSNotificationObserver alloc] |
| + initForNotification:NSWindowDidMiniaturizeNotification]); |
| + |
| + // Position this on the minimize button. |
| + NSEvent* mouse_down = cocoa_test_event_utils::LeftMouseDownAtPointInWindow( |
| + NSMakePoint(30, 290), widget.GetNativeWindow()); |
| + CGEventPost(kCGSessionEventTap, [mouse_down CGEvent]); |
| + |
| + NSEvent* mouse_up = cocoa_test_event_utils::MouseEventAtPointInWindow( |
| + NSMakePoint(30, 290), NSLeftMouseUp, widget.GetNativeWindow(), 0); |
| + CGEventPost(kCGSessionEventTap, [mouse_up CGEvent]); |
| + |
| + [ns_observer wait]; |
| + [widget.GetNativeWindow() deminiaturize:nil]; |
|
tapted
2015/06/03 07:04:50
before this, EXPECT_TRUE([widget.GetNativeWindow()
jackhou1
2015/06/03 08:13:52
Done.
|
| + |
| + // Position unchanged. |
| + EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x); |
| + } |
| + |
| + // Non-draggable areas should do nothing. |
| + frame_view->set_hit_test_result(HTCLIENT); |
| + { |
| + EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x); |
| + |
| + NSEvent* mouse_down = cocoa_test_event_utils::LeftMouseDownAtPointInWindow( |
| + NSMakePoint(10, 10), widget.GetNativeWindow()); |
| + CGEventPost(kCGSessionEventTap, [mouse_down CGEvent]); |
| + WaitForEvent(NSLeftMouseDownMask); |
| + |
| + NSEvent* mouse_drag = cocoa_test_event_utils::MouseEventAtPointInWindow( |
| + NSMakePoint(110, 110), NSLeftMouseDragged, widget.GetNativeWindow(), 0); |
| + CGEventPost(kCGSessionEventTap, [mouse_drag CGEvent]); |
| + WaitForEvent(NSLeftMouseDraggedMask); |
| + EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x); |
| + |
| + NSEvent* mouse_up = cocoa_test_event_utils::MouseEventAtPointInWindow( |
| + NSMakePoint(110, 110), NSLeftMouseUp, widget.GetNativeWindow(), 0); |
| + CGEventPost(kCGSessionEventTap, [mouse_up CGEvent]); |
| + WaitForEvent(NSLeftMouseUpMask); |
| + EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x); |
| + } |
| +} |
| + |
| +} // namespace test |
| } // namespace views |