OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/ui/cocoa/base_bubble_controller.h" | 5 #import "chrome/browser/ui/cocoa/base_bubble_controller.h" |
6 | 6 |
7 #include "base/mac/mac_util.h" | 7 #include "base/mac/mac_util.h" |
8 #import "base/mac/scoped_nsobject.h" | 8 #import "base/mac/scoped_nsobject.h" |
9 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h" | 9 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h" |
10 #import "chrome/browser/ui/cocoa/info_bubble_view.h" | 10 #import "chrome/browser/ui/cocoa/info_bubble_view.h" |
11 #import "chrome/browser/ui/cocoa/run_loop_testing.h" | 11 #import "chrome/browser/ui/cocoa/run_loop_testing.h" |
12 #import "ui/events/test/cocoa_test_event_utils.h" | 12 #import "ui/events/test/cocoa_test_event_utils.h" |
13 | 13 |
14 namespace { | 14 namespace { |
15 const CGFloat kBubbleWindowWidth = 100; | 15 const CGFloat kBubbleWindowWidth = 100; |
16 const CGFloat kBubbleWindowHeight = 50; | 16 const CGFloat kBubbleWindowHeight = 50; |
17 const CGFloat kAnchorPointX = 400; | 17 const CGFloat kAnchorPointX = 400; |
18 const CGFloat kAnchorPointY = 300; | 18 const CGFloat kAnchorPointY = 300; |
19 } // namespace | 19 } // namespace |
20 | 20 |
21 @interface ContextMenuController : NSObject<NSMenuDelegate> { | |
22 @private | |
Robert Sesek
2014/06/05 14:22:50
nit: @private is only indented 1 space
| |
23 NSMenu* menu_; | |
24 NSWindow* window_; | |
25 BOOL isMenuOpen_; | |
26 BOOL didOpen_; | |
27 } | |
28 | |
29 - (id)initWithMenu:(NSMenu*) menu AndWindow:(NSWindow*) window; | |
Robert Sesek
2014/06/05 14:22:50
nit: No space after ) for arguments. I'm mentionin
Robert Sesek
2014/06/05 14:22:50
nit: AndWindow: -> andWindow:
| |
30 | |
31 - (BOOL)isMenuOpen; | |
32 - (BOOL)didOpen; | |
33 - (BOOL)isWindowVisible; | |
34 | |
35 // NSMenuDelegate methods | |
36 - (void)menuWillOpen:(NSMenu*) menu; | |
37 - (void)menuDidClose:(NSMenu*) menu; | |
38 | |
39 @end | |
40 | |
41 @implementation ContextMenuController | |
42 | |
43 - (id)initWithMenu:(NSMenu*) menu AndWindow:(NSWindow*)window { | |
44 if (self = [super init]) { | |
45 menu_ = menu; | |
46 window_ = window; | |
47 isMenuOpen_ = NO; | |
48 didOpen_ = NO; | |
49 [menu_ setDelegate: self]; | |
Robert Sesek
2014/06/05 14:22:50
nit: No space after : in method invocations. Pleas
| |
50 } | |
51 return self; | |
52 } | |
53 | |
54 - (BOOL)isMenuOpen { | |
55 return isMenuOpen_; | |
56 } | |
57 | |
58 - (BOOL)didOpen { | |
59 return didOpen_; | |
60 } | |
61 | |
62 - (BOOL)isWindowVisible { | |
63 if (window_) { | |
64 return [window_ isVisible]; | |
65 } | |
66 return NO; | |
67 } | |
68 | |
69 - (void)menuWillOpen:(NSMenu *)menu { | |
Robert Sesek
2014/06/05 14:22:50
nit: No space before * in arguments. Same with lin
| |
70 isMenuOpen_ = YES; | |
71 didOpen_ = NO; | |
72 | |
73 NSArray* modes = [NSArray arrayWithObjects:NSEventTrackingRunLoopMode, | |
Robert Sesek
2014/06/05 14:22:50
You can use the ObjC array literal syntax @[ NSEve
| |
74 NSDefaultRunLoopMode, | |
75 nil]; | |
76 [menu_ performSelector:@selector(cancelTracking) | |
77 withObject:nil | |
78 afterDelay:0.1 | |
79 inModes:modes]; | |
80 } | |
81 | |
82 - (void)menuDidClose:(NSMenu *)menu { | |
83 isMenuOpen_ = NO; | |
84 didOpen_ = YES; | |
85 } | |
86 | |
87 @end | |
88 | |
21 class BaseBubbleControllerTest : public CocoaTest { | 89 class BaseBubbleControllerTest : public CocoaTest { |
22 public: | 90 public: |
23 virtual void SetUp() OVERRIDE { | 91 virtual void SetUp() OVERRIDE { |
24 bubbleWindow_.reset([[NSWindow alloc] | 92 bubbleWindow_.reset([[NSWindow alloc] |
25 initWithContentRect:NSMakeRect(0, 0, kBubbleWindowWidth, | 93 initWithContentRect:NSMakeRect(0, 0, kBubbleWindowWidth, |
26 kBubbleWindowHeight) | 94 kBubbleWindowHeight) |
27 styleMask:NSBorderlessWindowMask | 95 styleMask:NSBorderlessWindowMask |
28 backing:NSBackingStoreBuffered | 96 backing:NSBackingStoreBuffered |
29 defer:YES]); | 97 defer:YES]); |
30 | 98 |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
167 else | 235 else |
168 [controller_ windowDidResignKey:notif]; | 236 [controller_ windowDidResignKey:notif]; |
169 | 237 |
170 | 238 |
171 EXPECT_FALSE([bubble_window isVisible]); | 239 EXPECT_FALSE([bubble_window isVisible]); |
172 EXPECT_TRUE([other_window isVisible]); | 240 EXPECT_TRUE([other_window isVisible]); |
173 } | 241 } |
174 | 242 |
175 // Test that clicking outside the window causes the bubble to close if | 243 // Test that clicking outside the window causes the bubble to close if |
176 // shouldCloseOnResignKey is YES. | 244 // shouldCloseOnResignKey is YES. |
177 TEST_F(BaseBubbleControllerTest, LionClickOutsideCloses) { | 245 TEST_F(BaseBubbleControllerTest, LionClickOutsideClosesWithoutContextMenu) { |
178 // The event tap is only installed on 10.7+. | 246 // The event tap is only installed on 10.7+. |
179 if (!base::mac::IsOSLionOrLater()) | 247 if (!base::mac::IsOSLionOrLater()) |
180 return; | 248 return; |
181 | 249 |
182 // Closing the bubble will autorelease the controller. | 250 // Closing the bubble will autorelease the controller. |
183 base::scoped_nsobject<BaseBubbleController> keep_alive([controller_ retain]); | 251 base::scoped_nsobject<BaseBubbleController> keep_alive([controller_ retain]); |
184 NSWindow* window = [controller_ window]; | 252 NSWindow* window = [controller_ window]; |
185 | 253 |
186 EXPECT_TRUE([controller_ shouldCloseOnResignKey]); // Verify default value. | 254 EXPECT_TRUE([controller_ shouldCloseOnResignKey]); // Verify default value. |
187 EXPECT_FALSE([window isVisible]); | 255 EXPECT_FALSE([window isVisible]); |
188 | 256 |
189 [controller_ showWindow:nil]; | 257 [controller_ showWindow:nil]; |
190 | 258 |
191 EXPECT_TRUE([window isVisible]); | 259 EXPECT_TRUE([window isVisible]); |
192 | 260 |
193 [controller_ setShouldCloseOnResignKey:NO]; | 261 [controller_ setShouldCloseOnResignKey:NO]; |
194 NSEvent* event = cocoa_test_event_utils::LeftMouseDownAtPointInWindow( | 262 NSEvent* event = cocoa_test_event_utils::LeftMouseDownAtPointInWindow( |
195 NSMakePoint(10, 10), test_window()); | 263 NSMakePoint(10, 10), test_window()); |
196 [NSApp sendEvent:event]; | 264 [NSApp sendEvent:event]; |
197 chrome::testing::NSRunLoopRunAllPending(); | |
Robert Sesek
2014/06/05 14:22:50
What's the rationale for removing these calls?
Xuefei Ren
2014/06/06 03:41:44
Before my patch, the bubble window close depends o
| |
198 | 265 |
199 EXPECT_TRUE([window isVisible]); | 266 EXPECT_TRUE([window isVisible]); |
200 | 267 |
268 event = cocoa_test_event_utils::RightMouseDownAtPointInWindow( | |
269 NSMakePoint(10, 10), test_window()); | |
270 [NSApp sendEvent:event]; | |
271 | |
272 EXPECT_TRUE([window isVisible]); | |
273 | |
201 [controller_ setShouldCloseOnResignKey:YES]; | 274 [controller_ setShouldCloseOnResignKey:YES]; |
202 event = cocoa_test_event_utils::LeftMouseDownAtPointInWindow( | 275 event = cocoa_test_event_utils::LeftMouseDownAtPointInWindow( |
203 NSMakePoint(10, 10), test_window()); | 276 NSMakePoint(10, 10), test_window()); |
204 [NSApp sendEvent:event]; | 277 [NSApp sendEvent:event]; |
205 chrome::testing::NSRunLoopRunAllPending(); | 278 |
279 EXPECT_FALSE([window isVisible]); | |
280 | |
281 [controller_ showWindow:nil]; // Show it again | |
282 EXPECT_TRUE([window isVisible]); | |
283 EXPECT_TRUE([controller_ shouldCloseOnResignKey]); // Verify. | |
284 | |
285 event = cocoa_test_event_utils::RightMouseDownAtPointInWindow( | |
286 NSMakePoint(10, 10), test_window()); | |
287 [NSApp sendEvent:event]; | |
206 | 288 |
207 EXPECT_FALSE([window isVisible]); | 289 EXPECT_FALSE([window isVisible]); |
208 } | 290 } |
291 | |
292 // Test that right-clicking the window with displaying a context menu causes | |
293 // the bubble to close. | |
294 TEST_F(BaseBubbleControllerTest, LionRightClickOutsideClosesWithContextMenu) { | |
295 // The event tap is only installed on 10.7+. | |
296 if (!base::mac::IsOSLionOrLater()) | |
297 return; | |
298 | |
299 // Closing the bubble will autorelease the controller. | |
300 base::scoped_nsobject<BaseBubbleController> keep_alive([controller_ retain]); | |
301 NSWindow* window = [controller_ window]; | |
302 | |
303 EXPECT_TRUE([controller_ shouldCloseOnResignKey]); // Verify default value. | |
304 EXPECT_FALSE([window isVisible]); | |
305 | |
306 [controller_ showWindow:nil]; | |
307 | |
308 EXPECT_TRUE([window isVisible]); | |
309 | |
310 base::scoped_nsobject<NSMenu> context_menu( | |
311 [[NSMenu alloc] initWithTitle:@""]); | |
Robert Sesek
2014/06/05 14:22:50
nit: Only indent 6 spaces total.
| |
312 [context_menu addItemWithTitle: @"ContextMenuTest" | |
313 action: nil | |
314 keyEquivalent:@""]; | |
315 ContextMenuController* menu_controller = [[ContextMenuController alloc] | |
Robert Sesek
2014/06/05 14:22:50
This is leaked, so you should put it in a scoped_n
| |
316 initWithMenu: context_menu | |
317 AndWindow: window]; | |
318 // Set the menu as the contextual menu of contentView of test_window(). | |
319 [[test_window() contentView] setMenu:context_menu]; | |
320 | |
321 // RightMouseDown in test_window() would close the bubble window and then | |
322 // dispaly the contextual menu. | |
323 NSEvent* event = cocoa_test_event_utils::RightMouseDownAtPointInWindow( | |
324 NSMakePoint(10, 10), | |
Robert Sesek
2014/06/05 14:22:50
nit: Only indent 6 spaces total, and you can join
| |
325 test_window()); | |
326 // Verify bubble's window is closed when contextual menu is open. | |
327 CFRunLoopPerformBlock(CFRunLoopGetCurrent(), NSEventTrackingRunLoopMode, ^{ | |
328 EXPECT_TRUE([menu_controller isMenuOpen]); | |
Robert Sesek
2014/06/05 14:22:50
nit: Indent blocks 4 spaces.
| |
329 EXPECT_FALSE([menu_controller isWindowVisible]); | |
330 }); | |
331 | |
332 EXPECT_FALSE([menu_controller isMenuOpen]); | |
333 EXPECT_FALSE([menu_controller didOpen]); | |
334 | |
335 [NSApp sendEvent:event]; | |
336 | |
337 // When we got here, menu has already run its RunLoop. | |
338 // See ContextualMenuController::MenuWillOpen. | |
Robert Sesek
2014/06/05 14:22:50
This is how you name a C++ method. This should be
| |
339 EXPECT_FALSE([window isVisible]); | |
340 | |
341 EXPECT_FALSE([menu_controller isMenuOpen]); | |
342 EXPECT_TRUE([menu_controller didOpen]); | |
343 } | |
344 | |
OLD | NEW |