1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #import <Cocoa/Cocoa.h> 6 7 #import "base/mac/scoped_nsobject.h" 8 #include "chrome/app/chrome_command_ids.h" 9 #import "chrome/browser/ui/cocoa/cocoa_test_helper.h" 10 #import "chrome/browser/ui/cocoa/toolbar/toolbar_button.h" 11 #import "testing/gtest_mac.h" 12 #import "ui/events/test/cocoa_test_event_utils.h" 13 14 @interface TestableToolbarButton : ToolbarButton { 15 @private 16 NSInteger numOfClick_; 17 NSInteger lastCommand_; 18 } 19 20 @property(assign, nonatomic) NSInteger numOfClick; 21 @property(assign, nonatomic) NSInteger lastCommand; 22 23 - (id)initWithFrame:(NSRect)frame; 24 - (void)doAction:(id)sender; 25 @end 26 27 @implementation TestableToolbarButton 28 29 @synthesize numOfClick = numOfClick_; 30 @synthesize lastCommand = lastCommand_; 31 32 - (id)initWithFrame:(NSRect)frame { 33 if ((self = [super initWithFrame:frame])) { 34 lastCommand_ = IDC_STOP; 35 } 36 return self; 37 } 38 39 - (void)doAction:(id)sender { 40 lastCommand_ = [sender tag]; 41 if (lastCommand_ == [self tag]) 42 ++numOfClick_; 43 } 44 45 - (BOOL)shouldHandleEvent:(NSEvent*)theEvent { 46 return handleMiddleClick_; 47 } 48 49 @end 50 51 namespace { 52 53 class ToolbarButtonTest : public CocoaTest { 54 public: 55 ToolbarButtonTest() { 56 NSRect frame = NSMakeRect(0, 0, 20, 20); 57 base::scoped_nsobject<TestableToolbarButton> button( 58 [[TestableToolbarButton alloc] initWithFrame:frame]); 59 button_ = button.get(); 60 61 [button_ setTag:IDC_HOME]; 62 [button_ setTarget:button_]; 63 [button_ setAction:@selector(doAction:)]; 64 [[test_window() contentView] addSubview:button_]; 65 66 NSRect bounds = [button_ bounds]; 67 NSPoint mid_point = NSMakePoint(NSMidX(bounds), NSMidY(bounds)); 68 NSPoint out_point = NSMakePoint(bounds.origin.x - 10, 69 bounds.origin.y - 10); 70 left_down_in_view = 71 cocoa_test_event_utils::MouseEventAtPoint(mid_point, 72 NSLeftMouseDown, 73 0); 74 left_up_in_view = 75 cocoa_test_event_utils::MouseEventAtPoint(mid_point, 76 NSLeftMouseUp, 77 0); 78 right_down_in_view = 79 cocoa_test_event_utils::MouseEventAtPoint(mid_point, 80 NSRightMouseDown, 81 0); 82 right_up_in_view = 83 cocoa_test_event_utils::MouseEventAtPoint(mid_point, 84 NSRightMouseUp, 85 0); 86 other_down_in_view = 87 cocoa_test_event_utils::MouseEventAtPoint(mid_point, 88 NSOtherMouseDown, 89 0); 90 other_dragged_in_view = 91 cocoa_test_event_utils::MouseEventAtPoint(mid_point, 92 NSOtherMouseDragged, 93 0); 94 other_up_in_view = 95 cocoa_test_event_utils::MouseEventAtPoint(mid_point, 96 NSOtherMouseUp, 97 0); 98 other_down_out_view = 99 cocoa_test_event_utils::MouseEventAtPoint(out_point, 100 NSOtherMouseDown, 101 0); 102 other_dragged_out_view = 103 cocoa_test_event_utils::MouseEventAtPoint(out_point, 104 NSOtherMouseDragged, 105 0); 106 other_up_out_view = 107 cocoa_test_event_utils::MouseEventAtPoint(out_point, 108 NSOtherMouseUp, 109 0); 110 } 111 112 TestableToolbarButton* button_; 113 NSEvent* left_down_in_view; 114 NSEvent* left_up_in_view; 115 NSEvent* right_down_in_view; 116 NSEvent* right_up_in_view; 117 NSEvent* other_down_in_view; 118 NSEvent* other_dragged_in_view; 119 NSEvent* other_up_in_view; 120 NSEvent* other_down_out_view; 121 NSEvent* other_dragged_out_view; 122 NSEvent* other_up_out_view; 123 }; 124 125 TEST_VIEW(ToolbarButtonTest, button_) 126 127 TEST_F(ToolbarButtonTest, DoesNotSwallowClicksOnNO) { 128 // Middle button being down doesn't swallow right button clicks. But 129 // ToolbarButton doesn't handle right button events. 130 [button_ otherMouseDown:other_down_in_view]; 131 EXPECT_EQ(NSOffState, [button_ state]); 132 [button_ rightMouseDown:right_down_in_view]; 133 EXPECT_EQ(NSOffState, [button_ state]); 134 [button_ rightMouseUp:right_up_in_view]; 135 EXPECT_EQ(NSOffState, [button_ state]); 136 EXPECT_EQ(0, [button_ numOfClick]); 137 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 138 [button_ otherMouseUp:other_up_in_view]; 139 EXPECT_EQ(NSOffState, [button_ state]); 140 EXPECT_EQ(0, [button_ numOfClick]); 141 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 142 143 // Middle button being down doesn't swallows left button clicks. 144 [button_ otherMouseDown:other_down_in_view]; 145 EXPECT_EQ(NSOffState, [button_ state]); 146 [NSApp postEvent:left_up_in_view atStart:YES]; 147 [button_ mouseDown:left_down_in_view]; 148 EXPECT_EQ(1, [button_ numOfClick]); 149 EXPECT_EQ(IDC_HOME, [button_ lastCommand]); 150 [button_ otherMouseUp:other_up_in_view]; 151 EXPECT_EQ(1, [button_ numOfClick]); 152 EXPECT_EQ(IDC_HOME, [button_ lastCommand]); 153 } 154 155 TEST_F(ToolbarButtonTest, WithoutMouseDownOnNO) { 156 // Middle button mouse up without leading mouse down in the view. 157 [button_ otherMouseUp:other_up_in_view]; 158 EXPECT_EQ(NSOffState, [button_ state]); 159 EXPECT_EQ(0, [button_ numOfClick]); 160 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 161 162 // Middle button mouse dragged in the view and up without leading mouse down. 163 [button_ otherMouseDragged:other_dragged_in_view]; 164 EXPECT_EQ(NSOffState, [button_ state]); 165 [button_ otherMouseUp:other_up_in_view]; 166 EXPECT_EQ(NSOffState, [button_ state]); 167 EXPECT_EQ(0, [button_ numOfClick]); 168 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 169 } 170 171 TEST_F(ToolbarButtonTest, MouseClickOnNO) { 172 // Middle button clicking in the view. 173 [button_ otherMouseDown:other_down_in_view]; 174 EXPECT_EQ(NSOffState, [button_ state]); 175 [button_ otherMouseUp:other_up_in_view]; 176 EXPECT_EQ(NSOffState, [button_ state]); 177 EXPECT_EQ(0, [button_ numOfClick]); 178 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 179 180 // Middle button clicking outside of the view. 181 [button_ otherMouseDown:other_down_out_view]; 182 EXPECT_EQ(NSOffState, [button_ state]); 183 [button_ otherMouseUp:other_up_out_view]; 184 EXPECT_EQ(NSOffState, [button_ state]); 185 EXPECT_EQ(0, [button_ numOfClick]); 186 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 187 } 188 189 TEST_F(ToolbarButtonTest, MouseDraggingOnNO) { 190 // Middle button being down in the view and up outside of the view. 191 [button_ otherMouseDown:other_down_in_view]; 192 EXPECT_EQ(NSOffState, [button_ state]); 193 [button_ otherMouseDragged:other_dragged_out_view]; 194 EXPECT_EQ(NSOffState, [button_ state]); 195 [button_ otherMouseUp:other_up_out_view]; 196 EXPECT_EQ(NSOffState, [button_ state]); 197 EXPECT_EQ(0, [button_ numOfClick]); 198 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 199 200 // Middle button being down on the button, move to outside and move on it 201 // again, then up on the button. 202 [button_ otherMouseDown:other_down_in_view]; 203 EXPECT_EQ(NSOffState, [button_ state]); 204 [button_ otherMouseDragged:other_dragged_in_view]; 205 EXPECT_EQ(NSOffState, [button_ state]); 206 [button_ otherMouseUp:other_up_in_view]; 207 EXPECT_EQ(NSOffState, [button_ state]); 208 EXPECT_EQ(0, [button_ numOfClick]); 209 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 210 } 211 212 TEST_F(ToolbarButtonTest, WithoutMouseDownOnYES) { 213 // Enable middle button handling. 214 [button_ setHandleMiddleClick:YES]; 215 216 // Middle button mouse up without leading mouse down in the view. 217 [button_ otherMouseUp:other_up_in_view]; 218 EXPECT_EQ(NSOffState, [button_ state]); 219 EXPECT_EQ(0, [button_ numOfClick]); 220 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 221 222 // Middle button mouse dragged in the view and up without leading mouse down. 223 [button_ otherMouseDragged:other_dragged_in_view]; 224 EXPECT_EQ(NSOffState, [button_ state]); 225 [button_ otherMouseUp:other_up_in_view]; 226 EXPECT_EQ(NSOffState, [button_ state]); 227 EXPECT_EQ(0, [button_ numOfClick]); 228 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 229 } 230 231 TEST_F(ToolbarButtonTest, MouseClickInsideOnYES) { 232 // Enable middle button handling. 233 [button_ setHandleMiddleClick:YES]; 234 235 // Middle button clicking in the view. 236 [NSApp postEvent:other_up_in_view atStart:YES]; 237 [button_ otherMouseDown:other_down_in_view]; 238 239 EXPECT_EQ(NSOffState, [button_ state]); 240 EXPECT_EQ(1, [button_ numOfClick]); 241 EXPECT_EQ(IDC_HOME, [button_ lastCommand]); 242 } 243 244 TEST_F(ToolbarButtonTest, MouseClickOutsideOnYES) { 245 // Enable middle button handling. 246 [button_ setHandleMiddleClick:YES]; 247 248 // Middle button clicking outside of the view. 249 [NSApp postEvent:other_up_out_view atStart:YES]; 250 [button_ otherMouseDown:other_down_out_view]; 251 252 EXPECT_EQ(NSOffState, [button_ state]); 253 EXPECT_EQ(0, [button_ numOfClick]); 254 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 255 } 256 257 TEST_F(ToolbarButtonTest, MouseDraggingOnYES) { 258 // Enable middle button handling. 259 [button_ setHandleMiddleClick:YES]; 260 261 // Middle button being down in the view and up outside of the view. 262 [NSApp postEvent:other_up_out_view atStart:YES]; 263 [NSApp postEvent:other_dragged_out_view atStart:YES]; 264 [button_ otherMouseDown:other_down_in_view]; 265 266 EXPECT_EQ(NSOffState, [button_ state]); 267 EXPECT_EQ(0, [button_ numOfClick]); 268 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 269 270 // Middle button being down on the button, move to outside and move on it 271 // again, then up on the button. 272 [NSApp postEvent:other_up_in_view atStart:YES]; 273 [NSApp postEvent:other_dragged_in_view atStart:YES]; 274 [NSApp postEvent:other_dragged_out_view atStart:YES]; 275 [button_ otherMouseDown:other_down_in_view]; 276 277 EXPECT_EQ(NSOffState, [button_ state]); 278 EXPECT_EQ(1, [button_ numOfClick]); 279 EXPECT_EQ(IDC_HOME, [button_ lastCommand]); 280 } 281 282 TEST_F(ToolbarButtonTest, DoesSwallowRightClickOnYES) { 283 // Enable middle button handling. 284 [button_ setHandleMiddleClick:YES]; 285 286 // Middle button being down should swallow right button clicks. 287 [NSApp postEvent:other_up_in_view atStart:YES]; 288 [NSApp postEvent:right_up_in_view atStart:YES]; 289 [NSApp postEvent:right_down_in_view atStart:YES]; 290 [button_ otherMouseDown:other_down_in_view]; 291 292 EXPECT_EQ(NSOffState, [button_ state]); 293 EXPECT_EQ(1, [button_ numOfClick]); 294 EXPECT_EQ(IDC_HOME, [button_ lastCommand]); 295 } 296 297 TEST_F(ToolbarButtonTest, DoesSwallowLeftClickOnYES) { 298 // Enable middle button handling. 299 [button_ setHandleMiddleClick:YES]; 300 301 // Middle button being down swallows left button clicks. 302 [NSApp postEvent:other_up_in_view atStart:YES]; 303 [NSApp postEvent:left_up_in_view atStart:YES]; 304 [NSApp postEvent:left_down_in_view atStart:YES]; 305 [button_ otherMouseDown:other_down_in_view]; 306 307 EXPECT_EQ(NSOffState, [button_ state]); 308 EXPECT_EQ(1, [button_ numOfClick]); 309 EXPECT_EQ(IDC_HOME, [button_ lastCommand]); 310 } 311 312 } // namespace 313