Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Unified Diff: ui/views/cocoa/bridged_native_widget_interactive_uitest.mm

Issue 1146873002: [MacViews] Enable dragging a window by its caption/draggable areas. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Sync and rebase Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698