OLD | NEW |
---|---|
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 #import "ui/base/test/windowed_nsnotification_observer.h" | |
14 #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.
| |
12 #include "ui/views/test/widget_test.h" | 15 #include "ui/views/test/widget_test.h" |
16 #include "ui/views/window/native_frame_view.h" | |
13 | 17 |
14 namespace views { | 18 namespace views { |
19 namespace test { | |
15 | 20 |
16 class BridgedNativeWidgetUITest : public test::WidgetTest { | 21 class BridgedNativeWidgetUITest : public test::WidgetTest { |
17 public: | 22 public: |
18 BridgedNativeWidgetUITest() {} | 23 BridgedNativeWidgetUITest() {} |
19 | 24 |
20 // testing::Test: | 25 // testing::Test: |
21 void SetUp() override { | 26 void SetUp() override { |
22 WidgetTest::SetUp(); | 27 WidgetTest::SetUp(); |
23 Widget::InitParams init_params = | 28 Widget::InitParams init_params = |
24 CreateParams(Widget::InitParams::TYPE_WINDOW); | 29 CreateParams(Widget::InitParams::TYPE_WINDOW); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
137 widget_->SetFullscreen(false); | 142 widget_->SetFullscreen(false); |
138 EXPECT_FALSE(widget_->IsFullscreen()); | 143 EXPECT_FALSE(widget_->IsFullscreen()); |
139 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds()); | 144 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds()); |
140 | 145 |
141 [waiter waitForEnterCount:1 exitCount:1]; | 146 [waiter waitForEnterCount:1 exitCount:1]; |
142 EXPECT_EQ(1, [waiter enterCount]); | 147 EXPECT_EQ(1, [waiter enterCount]); |
143 EXPECT_EQ(1, [waiter exitCount]); | 148 EXPECT_EQ(1, [waiter exitCount]); |
144 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds()); | 149 EXPECT_EQ(restored_bounds, widget_->GetRestoredBounds()); |
145 } | 150 } |
146 | 151 |
152 namespace { | |
153 | |
154 // This is used to wait for reposted events to be seen. We can't just use | |
155 // RunPendingMessages() because CGEventPost might not be synchronous. | |
156 class HitTestBridgedNativeWidget : public BridgedNativeWidget { | |
157 public: | |
158 HitTestBridgedNativeWidget(NativeWidgetMac* widget) | |
tapted
2015/06/03 07:04:50
nit:explicit
jackhou1
2015/06/03 08:13:53
Done.
| |
159 : BridgedNativeWidget(widget) {} | |
160 | |
161 bool ShouldRepostPendingLeftMouseDown(NSPoint location_in_window) override { | |
tapted
2015/06/03 07:04:50
nit: // BridgedNativeWidget:
jackhou1
2015/06/03 08:13:52
Done.
| |
162 bool draggable_before = [ns_view() mouseDownCanMoveWindow]; | |
163 bool should_repost = BridgedNativeWidget::ShouldRepostPendingLeftMouseDown( | |
164 location_in_window); | |
165 bool draggable_after = [ns_view() mouseDownCanMoveWindow]; | |
166 | |
167 if (run_loop_.get() && draggable_before && !draggable_after) | |
168 run_loop_->Quit(); | |
169 | |
170 return should_repost; | |
171 } | |
172 | |
173 void WaitForRepost() { | |
tapted
2015/06/03 07:04:50
maybe WaitForIsDraggableChange?
jackhou1
2015/06/03 08:13:52
Done.
| |
174 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.
| |
175 run_loop_->Run(); | |
176 } | |
177 | |
178 private: | |
179 scoped_ptr<base::RunLoop> run_loop_; | |
180 }; | |
tapted
2015/06/03 07:04:50
nit: DISALLOW(..
jackhou1
2015/06/03 08:13:53
Done.
| |
181 | |
182 // This is used to return a customized result to NonClientHitTest. | |
183 class HitTestNonClientFrameView : public NativeFrameView { | |
184 public: | |
185 HitTestNonClientFrameView(Widget* widget) | |
tapted
2015/06/03 07:04:50
nit: explciit
jackhou1
2015/06/03 08:13:52
Done.
| |
186 : NativeFrameView(widget), hit_test_result_(HTNOWHERE) {} | |
187 | |
188 // NonClientFrameView overrides: | |
189 int NonClientHitTest(const gfx::Point& point) override { | |
190 return hit_test_result_; | |
191 } | |
192 | |
193 void set_hit_test_result(int component) { hit_test_result_ = component; } | |
194 | |
195 private: | |
196 int hit_test_result_; | |
197 }; | |
tapted
2015/06/03 07:04:50
nit: DISALLOW_COPY_..
jackhou1
2015/06/03 08:13:52
Done.
| |
198 | |
199 void WaitForEvent(NSUInteger mask) { | |
200 // Pointer because the handler block captures local variables by copying. | |
201 base::RunLoop* run_loop = new base::RunLoop(); | |
202 id monitor = [NSEvent | |
203 addLocalMonitorForEventsMatchingMask:mask | |
204 handler:^NSEvent*(NSEvent* ns_event) { | |
205 run_loop->Quit(); | |
206 return ns_event; | |
207 }]; | |
208 run_loop->Run(); | |
209 [NSEvent removeMonitor:monitor]; | |
210 delete run_loop; | |
211 } | |
212 | |
213 } // namespace | |
214 | |
215 // This is used to inject test versions of NativeFrameView and | |
216 // BridgedNativeWidget. | |
217 class HitTestNativeWidgetMac : public NativeWidgetMac { | |
218 public: | |
219 HitTestNativeWidgetMac(internal::NativeWidgetDelegate* delegate, | |
220 NativeFrameView* native_frame_view) | |
221 : NativeWidgetMac(delegate), native_frame_view_(native_frame_view) { | |
222 NativeWidgetMac::bridge_.reset(new HitTestBridgedNativeWidget(this)); | |
223 } | |
224 | |
225 HitTestBridgedNativeWidget* bridge() { | |
226 return static_cast<HitTestBridgedNativeWidget*>( | |
227 NativeWidgetMac::bridge_.get()); | |
228 } | |
229 | |
230 // internal::NativeWidgetPrivate: | |
231 NonClientFrameView* CreateNonClientFrameView() override { | |
232 return native_frame_view_; | |
233 } | |
234 | |
235 private: | |
236 // Owned by Widget. | |
237 NativeFrameView* native_frame_view_; | |
238 }; | |
tapted
2015/06/03 07:04:50
nit: DISALLOW_COPY.. (one of these comments is re
jackhou1
2015/06/03 08:13:53
Done.
| |
239 | |
240 TEST_F(BridgedNativeWidgetUITest, HitTest) { | |
241 Widget widget; | |
242 HitTestNonClientFrameView* frame_view = | |
243 new HitTestNonClientFrameView(&widget); | |
244 test::HitTestNativeWidgetMac* native_widget = | |
245 new test::HitTestNativeWidgetMac(&widget, frame_view); | |
246 Widget::InitParams init_params = | |
247 CreateParams(Widget::InitParams::TYPE_WINDOW); | |
248 init_params.native_widget = native_widget; | |
249 init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
250 init_params.bounds = gfx::Rect(100, 200, 400, 300); | |
251 widget.Init(init_params); | |
252 widget.Show(); | |
253 RunPendingMessages(); | |
254 | |
255 // Dragging the window should work. | |
256 frame_view->set_hit_test_result(HTCAPTION); | |
257 { | |
258 EXPECT_EQ(100, [widget.GetNativeWindow() frame].origin.x); | |
259 | |
260 NSEvent* mouse_down = cocoa_test_event_utils::LeftMouseDownAtPointInWindow( | |
261 NSMakePoint(10, 10), widget.GetNativeWindow()); | |
262 CGEventPost(kCGSessionEventTap, [mouse_down CGEvent]); | |
263 native_widget->bridge()->WaitForRepost(); | |
264 | |
265 base::scoped_nsobject<WindowedNSNotificationObserver> ns_observer( | |
266 [[WindowedNSNotificationObserver alloc] | |
267 initForNotification:NSWindowDidMoveNotification]); | |
268 NSEvent* mouse_drag = cocoa_test_event_utils::MouseEventAtPointInWindow( | |
269 NSMakePoint(110, 110), NSLeftMouseDragged, widget.GetNativeWindow(), 0); | |
270 CGEventPost(kCGSessionEventTap, [mouse_drag CGEvent]); | |
271 [ns_observer wait]; | |
272 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x); | |
273 | |
274 NSEvent* mouse_up = cocoa_test_event_utils::MouseEventAtPointInWindow( | |
275 NSMakePoint(10, 10), NSLeftMouseUp, widget.GetNativeWindow(), 0); | |
276 CGEventPost(kCGSessionEventTap, [mouse_up CGEvent]); | |
277 WaitForEvent(NSLeftMouseUpMask); | |
278 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x); | |
279 } | |
280 | |
281 // Mouse-downs on the window controls should not be intercepted. | |
282 { | |
283 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x); | |
284 | |
285 base::scoped_nsobject<WindowedNSNotificationObserver> ns_observer( | |
286 [[WindowedNSNotificationObserver alloc] | |
287 initForNotification:NSWindowDidMiniaturizeNotification]); | |
288 | |
289 // Position this on the minimize button. | |
290 NSEvent* mouse_down = cocoa_test_event_utils::LeftMouseDownAtPointInWindow( | |
291 NSMakePoint(30, 290), widget.GetNativeWindow()); | |
292 CGEventPost(kCGSessionEventTap, [mouse_down CGEvent]); | |
293 | |
294 NSEvent* mouse_up = cocoa_test_event_utils::MouseEventAtPointInWindow( | |
295 NSMakePoint(30, 290), NSLeftMouseUp, widget.GetNativeWindow(), 0); | |
296 CGEventPost(kCGSessionEventTap, [mouse_up CGEvent]); | |
297 | |
298 [ns_observer wait]; | |
299 [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.
| |
300 | |
301 // Position unchanged. | |
302 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x); | |
303 } | |
304 | |
305 // Non-draggable areas should do nothing. | |
306 frame_view->set_hit_test_result(HTCLIENT); | |
307 { | |
308 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x); | |
309 | |
310 NSEvent* mouse_down = cocoa_test_event_utils::LeftMouseDownAtPointInWindow( | |
311 NSMakePoint(10, 10), widget.GetNativeWindow()); | |
312 CGEventPost(kCGSessionEventTap, [mouse_down CGEvent]); | |
313 WaitForEvent(NSLeftMouseDownMask); | |
314 | |
315 NSEvent* mouse_drag = cocoa_test_event_utils::MouseEventAtPointInWindow( | |
316 NSMakePoint(110, 110), NSLeftMouseDragged, widget.GetNativeWindow(), 0); | |
317 CGEventPost(kCGSessionEventTap, [mouse_drag CGEvent]); | |
318 WaitForEvent(NSLeftMouseDraggedMask); | |
319 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x); | |
320 | |
321 NSEvent* mouse_up = cocoa_test_event_utils::MouseEventAtPointInWindow( | |
322 NSMakePoint(110, 110), NSLeftMouseUp, widget.GetNativeWindow(), 0); | |
323 CGEventPost(kCGSessionEventTap, [mouse_up CGEvent]); | |
324 WaitForEvent(NSLeftMouseUpMask); | |
325 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x); | |
326 } | |
327 } | |
328 | |
329 } // namespace test | |
147 } // namespace views | 330 } // namespace views |
OLD | NEW |