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/memory/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/test_event_utils.h" 11#import "chrome/browser/ui/cocoa/toolbar/toolbar_button.h" 12#import "testing/gtest_mac.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 51namespace { 52 53class ToolbarButtonTest : public CocoaTest { 54 public: 55 ToolbarButtonTest() { 56 NSRect frame = NSMakeRect(0, 0, 20, 20); 57 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 test_event_utils::MouseEventAtPoint(mid_point, NSLeftMouseDown, 0); 72 left_up_in_view = 73 test_event_utils::MouseEventAtPoint(mid_point, NSLeftMouseUp, 0); 74 right_down_in_view = 75 test_event_utils::MouseEventAtPoint(mid_point, NSRightMouseDown, 0); 76 right_up_in_view = 77 test_event_utils::MouseEventAtPoint(mid_point, NSRightMouseUp, 0); 78 other_down_in_view = 79 test_event_utils::MouseEventAtPoint(mid_point, NSOtherMouseDown, 0); 80 other_dragged_in_view = 81 test_event_utils::MouseEventAtPoint(mid_point, NSOtherMouseDragged, 0); 82 other_up_in_view = 83 test_event_utils::MouseEventAtPoint(mid_point, NSOtherMouseUp, 0); 84 other_down_out_view = 85 test_event_utils::MouseEventAtPoint(out_point, NSOtherMouseDown, 0); 86 other_dragged_out_view = 87 test_event_utils::MouseEventAtPoint(out_point, NSOtherMouseDragged, 0); 88 other_up_out_view = 89 test_event_utils::MouseEventAtPoint(out_point, NSOtherMouseUp, 0); 90 } 91 92 TestableToolbarButton* button_; 93 NSEvent* left_down_in_view; 94 NSEvent* left_up_in_view; 95 NSEvent* right_down_in_view; 96 NSEvent* right_up_in_view; 97 NSEvent* other_down_in_view; 98 NSEvent* other_dragged_in_view; 99 NSEvent* other_up_in_view; 100 NSEvent* other_down_out_view; 101 NSEvent* other_dragged_out_view; 102 NSEvent* other_up_out_view; 103}; 104 105TEST_VIEW(ToolbarButtonTest, button_) 106 107TEST_F(ToolbarButtonTest, DoesNotSwallowClicksOnNO) { 108 // Middle button being down doesn't swallow right button clicks. But 109 // ToolbarButton doesn't handle right button events. 110 [button_ otherMouseDown:other_down_in_view]; 111 EXPECT_EQ(NSOffState, [button_ state]); 112 [button_ rightMouseDown:right_down_in_view]; 113 EXPECT_EQ(NSOffState, [button_ state]); 114 [button_ rightMouseUp:right_up_in_view]; 115 EXPECT_EQ(NSOffState, [button_ state]); 116 EXPECT_EQ(0, [button_ numOfClick]); 117 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 118 [button_ otherMouseUp:other_up_in_view]; 119 EXPECT_EQ(NSOffState, [button_ state]); 120 EXPECT_EQ(0, [button_ numOfClick]); 121 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 122 123 // Middle button being down doesn't swallows left button clicks. 124 [button_ otherMouseDown:other_down_in_view]; 125 EXPECT_EQ(NSOffState, [button_ state]); 126 [NSApp postEvent:left_up_in_view atStart:YES]; 127 [button_ mouseDown:left_down_in_view]; 128 EXPECT_EQ(1, [button_ numOfClick]); 129 EXPECT_EQ(IDC_HOME, [button_ lastCommand]); 130 [button_ otherMouseUp:other_up_in_view]; 131 EXPECT_EQ(1, [button_ numOfClick]); 132 EXPECT_EQ(IDC_HOME, [button_ lastCommand]); 133} 134 135TEST_F(ToolbarButtonTest, WithoutMouseDownOnNO) { 136 // Middle button mouse up without leading mouse down in the view. 137 [button_ otherMouseUp:other_up_in_view]; 138 EXPECT_EQ(NSOffState, [button_ state]); 139 EXPECT_EQ(0, [button_ numOfClick]); 140 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 141 142 // Middle button mouse dragged in the view and up without leading mouse down. 143 [button_ otherMouseDragged:other_dragged_in_view]; 144 EXPECT_EQ(NSOffState, [button_ state]); 145 [button_ otherMouseUp:other_up_in_view]; 146 EXPECT_EQ(NSOffState, [button_ state]); 147 EXPECT_EQ(0, [button_ numOfClick]); 148 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 149} 150 151TEST_F(ToolbarButtonTest, MouseClickOnNO) { 152 // Middle button clicking in the view. 153 [button_ otherMouseDown:other_down_in_view]; 154 EXPECT_EQ(NSOffState, [button_ state]); 155 [button_ otherMouseUp:other_up_in_view]; 156 EXPECT_EQ(NSOffState, [button_ state]); 157 EXPECT_EQ(0, [button_ numOfClick]); 158 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 159 160 // Middle button clicking outside of the view. 161 [button_ otherMouseDown:other_down_out_view]; 162 EXPECT_EQ(NSOffState, [button_ state]); 163 [button_ otherMouseUp:other_up_out_view]; 164 EXPECT_EQ(NSOffState, [button_ state]); 165 EXPECT_EQ(0, [button_ numOfClick]); 166 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 167} 168 169TEST_F(ToolbarButtonTest, MouseDraggingOnNO) { 170 // Middle button being down in the view and up outside of the view. 171 [button_ otherMouseDown:other_down_in_view]; 172 EXPECT_EQ(NSOffState, [button_ state]); 173 [button_ otherMouseDragged:other_dragged_out_view]; 174 EXPECT_EQ(NSOffState, [button_ state]); 175 [button_ otherMouseUp:other_up_out_view]; 176 EXPECT_EQ(NSOffState, [button_ state]); 177 EXPECT_EQ(0, [button_ numOfClick]); 178 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 179 180 // Middle button being down on the button, move to outside and move on it 181 // again, then up on the button. 182 [button_ otherMouseDown:other_down_in_view]; 183 EXPECT_EQ(NSOffState, [button_ state]); 184 [button_ otherMouseDragged:other_dragged_in_view]; 185 EXPECT_EQ(NSOffState, [button_ state]); 186 [button_ otherMouseUp:other_up_in_view]; 187 EXPECT_EQ(NSOffState, [button_ state]); 188 EXPECT_EQ(0, [button_ numOfClick]); 189 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 190} 191 192TEST_F(ToolbarButtonTest, WithoutMouseDownOnYES) { 193 // Enable middle button handling. 194 [button_ setHandleMiddleClick:YES]; 195 196 // Middle button mouse up without leading mouse down in the view. 197 [button_ otherMouseUp:other_up_in_view]; 198 EXPECT_EQ(NSOffState, [button_ state]); 199 EXPECT_EQ(0, [button_ numOfClick]); 200 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 201 202 // Middle button mouse dragged in the view and up without leading mouse down. 203 [button_ otherMouseDragged:other_dragged_in_view]; 204 EXPECT_EQ(NSOffState, [button_ state]); 205 [button_ otherMouseUp:other_up_in_view]; 206 EXPECT_EQ(NSOffState, [button_ state]); 207 EXPECT_EQ(0, [button_ numOfClick]); 208 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 209} 210 211TEST_F(ToolbarButtonTest, MouseClickInsideOnYES) { 212 // Enable middle button handling. 213 [button_ setHandleMiddleClick:YES]; 214 215 // Middle button clicking in the view. 216 [button_ otherMouseDown:other_down_in_view]; 217 EXPECT_EQ(NSOnState, [button_ state]); 218 [button_ otherMouseUp:other_up_in_view]; 219 EXPECT_EQ(NSOffState, [button_ state]); 220 EXPECT_EQ(1, [button_ numOfClick]); 221 EXPECT_EQ(IDC_HOME, [button_ lastCommand]); 222} 223 224TEST_F(ToolbarButtonTest, MouseClickOutsideOnYES) { 225 // Enable middle button handling. 226 [button_ setHandleMiddleClick:YES]; 227 228 // Middle button clicking outside of the view. 229 [button_ otherMouseDown:other_down_out_view]; 230 EXPECT_EQ(NSOffState, [button_ state]); 231 [button_ otherMouseUp:other_up_out_view]; 232 EXPECT_EQ(NSOffState, [button_ state]); 233 EXPECT_EQ(0, [button_ numOfClick]); 234 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 235} 236 237TEST_F(ToolbarButtonTest, MouseDraggingOnYES) { 238 // Enable middle button handling. 239 [button_ setHandleMiddleClick:YES]; 240 241 // Middle button being down in the view and up outside of the view. 242 [button_ otherMouseDown:other_down_in_view]; 243 EXPECT_EQ(NSOnState, [button_ state]); 244 [button_ otherMouseDragged:other_dragged_out_view]; 245 EXPECT_EQ(NSOffState, [button_ state]); 246 [button_ otherMouseUp:other_up_out_view]; 247 EXPECT_EQ(NSOffState, [button_ state]); 248 EXPECT_EQ(0, [button_ numOfClick]); 249 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 250 251 // Middle button being down on the button, move to outside and move on it 252 // again, then up on the button. 253 [button_ otherMouseDown:other_down_in_view]; 254 EXPECT_EQ(NSOnState, [button_ state]); 255 [button_ otherMouseDragged:other_dragged_out_view]; 256 EXPECT_EQ(NSOffState, [button_ state]); 257 [button_ otherMouseDragged:other_dragged_in_view]; 258 EXPECT_EQ(NSOnState, [button_ state]); 259 [button_ otherMouseUp:other_up_in_view]; 260 EXPECT_EQ(NSOffState, [button_ state]); 261 EXPECT_EQ(1, [button_ numOfClick]); 262 EXPECT_EQ(IDC_HOME, [button_ lastCommand]); 263} 264 265TEST_F(ToolbarButtonTest, DoesNotSwallowRightClickOnYES) { 266 // Enable middle button handling. 267 [button_ setHandleMiddleClick:YES]; 268 269 // Middle button being down should swallow right button clicks, but 270 // ToolbarButton doesn't swallow it because it doesn't handle right button 271 // events. 272 [button_ otherMouseDown:other_down_in_view]; 273 EXPECT_EQ(NSOnState, [button_ state]); 274 [button_ rightMouseDown:right_down_in_view]; 275 EXPECT_EQ(NSOnState, [button_ state]); 276 [button_ rightMouseUp:right_up_in_view]; 277 EXPECT_EQ(NSOnState, [button_ state]); 278 EXPECT_EQ(0, [button_ numOfClick]); 279 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 280 [button_ otherMouseUp:other_up_in_view]; 281 EXPECT_EQ(NSOffState, [button_ state]); 282 EXPECT_EQ(1, [button_ numOfClick]); 283 EXPECT_EQ(IDC_HOME, [button_ lastCommand]); 284} 285 286TEST_F(ToolbarButtonTest, DoesSwallowLeftClickOnYES) { 287 // Enable middle button handling. 288 [button_ setHandleMiddleClick:YES]; 289 290 // Middle button being down swallows left button clicks. 291 [button_ otherMouseDown:other_down_in_view]; 292 EXPECT_EQ(NSOnState, [button_ state]); 293 [NSApp postEvent:left_up_in_view atStart:YES]; 294 [button_ mouseDown:left_down_in_view]; 295 EXPECT_EQ(0, [button_ numOfClick]); 296 EXPECT_EQ(IDC_STOP, [button_ lastCommand]); 297 [button_ otherMouseUp:other_up_in_view]; 298 EXPECT_EQ(1, [button_ numOfClick]); 299 EXPECT_EQ(IDC_HOME, [button_ lastCommand]); 300} 301 302} // namespace 303