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

Side by Side 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: Change to single repost and [NSWindow setMovableByWindowBackground]. Created 5 years, 6 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "ui/views/cocoa/bridged_native_widget.h" 5 #import "ui/views/cocoa/bridged_native_widget.h"
6 6
7 #import <Cocoa/Cocoa.h> 7 #import <Cocoa/Cocoa.h>
8 8
9 #import "base/mac/mac_util.h" 9 #import "base/mac/mac_util.h"
10 #import "base/mac/sdk_forward_declarations.h" 10 #import "base/mac/sdk_forward_declarations.h"
11 #import "ui/base/test/nswindow_fullscreen_notification_waiter.h" 11 #import "ui/base/test/nswindow_fullscreen_notification_waiter.h"
12 #include "ui/base/hit_test.h"
13 #include "ui/events/test/cocoa_test_event_utils.h"
12 #include "ui/views/test/widget_test.h" 14 #include "ui/views/test/widget_test.h"
15 #include "ui/views/window/native_frame_view.h"
16
17 // Watches for NSNotifications from the default notification center.
18 @interface WindowedNSNotificationObserver : NSObject {
jackhou1 2015/06/02 06:33:09 This can probably be merged with the one in app_sh
tapted 2015/06/03 00:28:37 are they both called WindowedNSNotificationObserve
jackhou1 2015/06/03 04:04:44 Nope, this one is in macviews_interactive_ui_tests
tapted 2015/06/03 07:04:48 oh whoops - nope. #wirescrossed
19 @private
20 BOOL notificationReceived_;
21 scoped_ptr<base::RunLoop> runLoop_;
22 }
23
24 - (id)initForNotification:(NSString*)name;
25 - (void)observe:(NSNotification*)notification;
26 - (void)wait;
27 @end
28
29 @implementation WindowedNSNotificationObserver
30
31 - (id)initForNotification:(NSString*)name {
32 if (self = [super init]) {
33 [[NSNotificationCenter defaultCenter] addObserver:self
34 selector:@selector(observe:)
35 name:name
36 object:nil];
37 }
38 return self;
39 }
40
41 - (void)observe:(NSNotification*)notification {
42 [[NSNotificationCenter defaultCenter] removeObserver:self];
43 notificationReceived_ = YES;
44 if (runLoop_.get())
45 runLoop_->Quit();
46 }
47
48 - (void)wait {
49 if (notificationReceived_)
50 return;
51
52 runLoop_.reset(new base::RunLoop);
53 runLoop_->Run();
54 }
55
56 @end
13 57
14 namespace views { 58 namespace views {
tapted 2015/06/03 00:28:37 add namespace test { after this (i.e. whole file s
jackhou1 2015/06/03 04:04:44 Done.
15 59
16 class BridgedNativeWidgetUITest : public test::WidgetTest { 60 class BridgedNativeWidgetUITest : public test::WidgetTest {
17 public: 61 public:
18 BridgedNativeWidgetUITest() {} 62 BridgedNativeWidgetUITest() {}
19 63
20 // testing::Test: 64 // testing::Test:
21 void SetUp() override { 65 void SetUp() override {
22 WidgetTest::SetUp(); 66 WidgetTest::SetUp();
23 Widget::InitParams init_params = 67 Widget::InitParams init_params =
24 CreateParams(Widget::InitParams::TYPE_WINDOW); 68 CreateParams(Widget::InitParams::TYPE_WINDOW);
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 widget_->SetFullscreen(false); 181 widget_->SetFullscreen(false);
138 EXPECT_FALSE(widget_->IsFullscreen()); 182 EXPECT_FALSE(widget_->IsFullscreen());
139 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds()); 183 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds());
140 184
141 [waiter waitForEnterCount:1 exitCount:1]; 185 [waiter waitForEnterCount:1 exitCount:1];
142 EXPECT_EQ(1, [waiter enterCount]); 186 EXPECT_EQ(1, [waiter enterCount]);
143 EXPECT_EQ(1, [waiter exitCount]); 187 EXPECT_EQ(1, [waiter exitCount]);
144 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds()); 188 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds());
145 } 189 }
146 190
191 namespace {
192
193 // This is used to wait for reposted events to be seen. We can't just use
194 // RunPendingMessages() because CGEventPost might not be synchronous.
195 class HitTestBridgedNativeWidget : public BridgedNativeWidget {
196 public:
197 HitTestBridgedNativeWidget(NativeWidgetMac* widget)
198 : BridgedNativeWidget(widget) {}
199
200 bool ShouldRepostPendingLeftMouseDown(NSPoint location_in_window) override {
201 bool draggable_before = [ns_view() mouseDownCanMoveWindow];
202 bool should_repost = BridgedNativeWidget::ShouldRepostPendingLeftMouseDown(
203 location_in_window);
204 bool draggable_after = [ns_view() mouseDownCanMoveWindow];
205
206 if (run_loop_.get() && draggable_before && !draggable_after)
207 run_loop_->Quit();
208
209 return should_repost;
210 }
211
212 void WaitForRepost() {
213 run_loop_.reset(new base::RunLoop);
214 run_loop_->Run();
215 }
216
217 private:
218 scoped_ptr<base::RunLoop> run_loop_;
219 };
220
221 // This is used to return a customized result to NonClientHitTest.
222 class HitTestNonClientFrameView : public NativeFrameView {
223 public:
224 HitTestNonClientFrameView(Widget* widget)
225 : NativeFrameView(widget), hit_test_result_(HTNOWHERE) {}
226
227 // NonClientFrameView overrides:
228 int NonClientHitTest(const gfx::Point& point) override {
229 return hit_test_result_;
230 }
231
232 void set_hit_test_result(int component) { hit_test_result_ = component; }
233
234 private:
235 int hit_test_result_;
236 };
237
238 } // namespace
239
240 // This is used to inject test versions of NativeFrameView and
241 // BridgedNativeWidget.
242 // Outside anonymous namespace so NativeWidgetMac can friend this.
243 class HitTestNativeWidgetMac : public NativeWidgetMac {
244 public:
245 HitTestNativeWidgetMac(internal::NativeWidgetDelegate* delegate,
246 NativeFrameView* native_frame_view)
247 : NativeWidgetMac(delegate), native_frame_view_(native_frame_view) {
248 NativeWidgetMac::bridge_.reset(new HitTestBridgedNativeWidget(this));
249 }
250
251 HitTestBridgedNativeWidget* bridge() {
252 return static_cast<HitTestBridgedNativeWidget*>(
253 NativeWidgetMac::bridge_.get());
254 }
255
256 // internal::NativeWidgetPrivate:
257 NonClientFrameView* CreateNonClientFrameView() override {
258 return native_frame_view_;
259 }
260
261 private:
262 // Owned by Widget.
263 NativeFrameView* native_frame_view_;
264 };
265
266 TEST_F(BridgedNativeWidgetUITest, HitTest) {
267 Widget widget;
268 HitTestNonClientFrameView* frame_view =
269 new HitTestNonClientFrameView(&widget);
270 HitTestNativeWidgetMac* native_widget =
271 new HitTestNativeWidgetMac(&widget, frame_view);
272 Widget::InitParams init_params =
273 CreateParams(Widget::InitParams::TYPE_WINDOW);
274 init_params.native_widget = native_widget;
275 init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
276 init_params.bounds = gfx::Rect(100, 100, 400, 300);
277 widget.Init(init_params);
278 widget.Show();
279 RunPendingMessages();
280
281 frame_view->set_hit_test_result(HTCAPTION);
282 {
283 EXPECT_EQ(100, [widget.GetNativeWindow() frame].origin.x);
284
285 NSEvent* mouse_down = cocoa_test_event_utils::LeftMouseDownAtPointInWindow(
286 NSMakePoint(10, 10), widget.GetNativeWindow());
287 CGEventPost(kCGSessionEventTap, [mouse_down CGEvent]);
288 native_widget->bridge()->WaitForRepost();
289
290 base::scoped_nsobject<WindowedNSNotificationObserver> ns_observer(
291 [[WindowedNSNotificationObserver alloc]
292 initForNotification:NSWindowDidMoveNotification]);
293 NSEvent* mouse_drag = cocoa_test_event_utils::MouseEventAtPointInWindow(
294 NSMakePoint(110, 110), NSLeftMouseDragged, widget.GetNativeWindow(),
295 1u);
296 CGEventPost(kCGSessionEventTap, [mouse_drag CGEvent]);
297 [ns_observer wait];
298 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x);
299
300 NSEvent* mouse_up = cocoa_test_event_utils::MouseEventAtPointInWindow(
301 NSMakePoint(110, 110), NSLeftMouseUp, widget.GetNativeWindow(), 2u);
302 CGEventPost(kCGSessionEventTap, [mouse_up CGEvent]);
303 RunPendingMessages();
304 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x);
305 }
306
307 frame_view->set_hit_test_result(HTCLIENT);
308 {
309 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x);
310
311 NSEvent* mouse_down = cocoa_test_event_utils::LeftMouseDownAtPointInWindow(
312 NSMakePoint(10, 10), widget.GetNativeWindow());
313 CGEventPost(kCGSessionEventTap, [mouse_down CGEvent]);
314 RunPendingMessages();
jackhou1 2015/06/02 06:33:09 I suspect these are not actually waiting long enou
tapted 2015/06/03 00:28:37 hm.... for these kind of events, maybe not without
jackhou1 2015/06/03 04:04:44 Just ended up using a local event monitor. I had
315
316 NSEvent* mouse_drag = cocoa_test_event_utils::MouseEventAtPointInWindow(
317 NSMakePoint(110, 110), NSLeftMouseDragged, widget.GetNativeWindow(),
318 3u);
319 CGEventPost(kCGSessionEventTap, [mouse_drag CGEvent]);
320 RunPendingMessages();
321 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x);
322
323 NSEvent* mouse_up = cocoa_test_event_utils::MouseEventAtPointInWindow(
324 NSMakePoint(110, 110), NSLeftMouseUp, widget.GetNativeWindow(), 4u);
325 CGEventPost(kCGSessionEventTap, [mouse_up CGEvent]);
326 RunPendingMessages();
327 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x);
328 }
329 }
330
147 } // namespace views 331 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698