Chromium Code Reviews| 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 |