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

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: Sync and rebase 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
« no previous file with comments | « ui/views/cocoa/bridged_native_widget.mm ('k') | ui/views/cocoa/views_nswindow_delegate.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #import "ui/base/test/windowed_nsnotification_observer.h"
14 #import "ui/events/test/cocoa_test_event_utils.h"
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
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 explicit HitTestBridgedNativeWidget(NativeWidgetMac* widget)
159 : BridgedNativeWidget(widget) {}
160
161 // BridgedNativeWidget:
162 bool ShouldRepostPendingLeftMouseDown(NSPoint location_in_window) override {
163 bool draggable_before = [ns_view() mouseDownCanMoveWindow];
164 bool should_repost = BridgedNativeWidget::ShouldRepostPendingLeftMouseDown(
165 location_in_window);
166 bool draggable_after = [ns_view() mouseDownCanMoveWindow];
167
168 if (run_loop_ && draggable_before && !draggable_after)
169 run_loop_->Quit();
170
171 return should_repost;
172 }
173
174 void WaitForIsDraggableChange() {
175 base::RunLoop run_loop;
176 run_loop_ = &run_loop;
177 run_loop.Run();
178 run_loop_ = nullptr;
179 }
180
181 private:
182 base::RunLoop* run_loop_;
183
184 DISALLOW_COPY_AND_ASSIGN(HitTestBridgedNativeWidget);
185 };
186
187 // This is used to return a customized result to NonClientHitTest.
188 class HitTestNonClientFrameView : public NativeFrameView {
189 public:
190 explicit HitTestNonClientFrameView(Widget* widget)
191 : NativeFrameView(widget), hit_test_result_(HTNOWHERE) {}
192
193 // NonClientFrameView overrides:
194 int NonClientHitTest(const gfx::Point& point) override {
195 return hit_test_result_;
196 }
197
198 void set_hit_test_result(int component) { hit_test_result_ = component; }
199
200 private:
201 int hit_test_result_;
202
203 DISALLOW_COPY_AND_ASSIGN(HitTestNonClientFrameView);
204 };
205
206 void WaitForEvent(NSUInteger mask) {
207 // Pointer because the handler block captures local variables by copying.
208 base::RunLoop run_loop;
209 base::RunLoop* run_loop_ref = &run_loop;
210 id monitor = [NSEvent
211 addLocalMonitorForEventsMatchingMask:mask
212 handler:^NSEvent*(NSEvent* ns_event) {
213 run_loop_ref->Quit();
214 return ns_event;
215 }];
216 run_loop.Run();
217 [NSEvent removeMonitor:monitor];
218 }
219
220 } // namespace
221
222 // This is used to inject test versions of NativeFrameView and
223 // BridgedNativeWidget.
224 class HitTestNativeWidgetMac : public NativeWidgetMac {
225 public:
226 HitTestNativeWidgetMac(internal::NativeWidgetDelegate* delegate,
227 NativeFrameView* native_frame_view)
228 : NativeWidgetMac(delegate), native_frame_view_(native_frame_view) {
229 NativeWidgetMac::bridge_.reset(new HitTestBridgedNativeWidget(this));
230 }
231
232 HitTestBridgedNativeWidget* bridge() {
233 return static_cast<HitTestBridgedNativeWidget*>(
234 NativeWidgetMac::bridge_.get());
235 }
236
237 // internal::NativeWidgetPrivate:
238 NonClientFrameView* CreateNonClientFrameView() override {
239 return native_frame_view_;
240 }
241
242 private:
243 // Owned by Widget.
244 NativeFrameView* native_frame_view_;
245
246 DISALLOW_COPY_AND_ASSIGN(HitTestNativeWidgetMac);
247 };
248
249 TEST_F(BridgedNativeWidgetUITest, HitTest) {
250 Widget widget;
251 HitTestNonClientFrameView* frame_view =
252 new HitTestNonClientFrameView(&widget);
253 test::HitTestNativeWidgetMac* native_widget =
254 new test::HitTestNativeWidgetMac(&widget, frame_view);
255 Widget::InitParams init_params =
256 CreateParams(Widget::InitParams::TYPE_WINDOW);
257 init_params.native_widget = native_widget;
258 init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
259 init_params.bounds = gfx::Rect(100, 200, 400, 300);
260 widget.Init(init_params);
261 widget.Show();
262
263 // Dragging the window should work.
264 frame_view->set_hit_test_result(HTCAPTION);
265 {
266 EXPECT_EQ(100, [widget.GetNativeWindow() frame].origin.x);
267
268 NSEvent* mouse_down = cocoa_test_event_utils::LeftMouseDownAtPointInWindow(
269 NSMakePoint(10, 10), widget.GetNativeWindow());
270 CGEventPost(kCGSessionEventTap, [mouse_down CGEvent]);
271 native_widget->bridge()->WaitForIsDraggableChange();
272
273 base::scoped_nsobject<WindowedNSNotificationObserver> ns_observer(
274 [[WindowedNSNotificationObserver alloc]
275 initForNotification:NSWindowDidMoveNotification]);
276 NSEvent* mouse_drag = cocoa_test_event_utils::MouseEventAtPointInWindow(
277 NSMakePoint(110, 110), NSLeftMouseDragged, widget.GetNativeWindow(), 0);
278 CGEventPost(kCGSessionEventTap, [mouse_drag CGEvent]);
279 [ns_observer wait];
280 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x);
281
282 NSEvent* mouse_up = cocoa_test_event_utils::MouseEventAtPointInWindow(
283 NSMakePoint(10, 10), NSLeftMouseUp, widget.GetNativeWindow(), 0);
284 CGEventPost(kCGSessionEventTap, [mouse_up CGEvent]);
285 WaitForEvent(NSLeftMouseUpMask);
286 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x);
287 }
288
289 // Mouse-downs on the window controls should not be intercepted.
290 {
291 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x);
292
293 base::scoped_nsobject<WindowedNSNotificationObserver> ns_observer(
294 [[WindowedNSNotificationObserver alloc]
295 initForNotification:NSWindowDidMiniaturizeNotification]);
296
297 // Position this on the minimize button.
298 NSEvent* mouse_down = cocoa_test_event_utils::LeftMouseDownAtPointInWindow(
299 NSMakePoint(30, 290), widget.GetNativeWindow());
300 CGEventPost(kCGSessionEventTap, [mouse_down CGEvent]);
301
302 NSEvent* mouse_up = cocoa_test_event_utils::MouseEventAtPointInWindow(
303 NSMakePoint(30, 290), NSLeftMouseUp, widget.GetNativeWindow(), 0);
304 EXPECT_FALSE([widget.GetNativeWindow() isMiniaturized]);
305 CGEventPost(kCGSessionEventTap, [mouse_up CGEvent]);
306 [ns_observer wait];
307 EXPECT_TRUE([widget.GetNativeWindow() isMiniaturized]);
308 [widget.GetNativeWindow() deminiaturize:nil];
309
310 // Position unchanged.
311 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x);
312 }
313
314 // Non-draggable areas should do nothing.
315 frame_view->set_hit_test_result(HTCLIENT);
316 {
317 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x);
318
319 NSEvent* mouse_down = cocoa_test_event_utils::LeftMouseDownAtPointInWindow(
320 NSMakePoint(10, 10), widget.GetNativeWindow());
321 CGEventPost(kCGSessionEventTap, [mouse_down CGEvent]);
322 WaitForEvent(NSLeftMouseDownMask);
323
324 NSEvent* mouse_drag = cocoa_test_event_utils::MouseEventAtPointInWindow(
325 NSMakePoint(110, 110), NSLeftMouseDragged, widget.GetNativeWindow(), 0);
326 CGEventPost(kCGSessionEventTap, [mouse_drag CGEvent]);
327 WaitForEvent(NSLeftMouseDraggedMask);
328 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x);
329
330 NSEvent* mouse_up = cocoa_test_event_utils::MouseEventAtPointInWindow(
331 NSMakePoint(110, 110), NSLeftMouseUp, widget.GetNativeWindow(), 0);
332 CGEventPost(kCGSessionEventTap, [mouse_up CGEvent]);
333 WaitForEvent(NSLeftMouseUpMask);
334 EXPECT_EQ(200, [widget.GetNativeWindow() frame].origin.x);
335 }
336 }
337
338 } // namespace test
147 } // namespace views 339 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/cocoa/bridged_native_widget.mm ('k') | ui/views/cocoa/views_nswindow_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698