Home | History | Annotate | Download | only in toolbar
      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 
     51 namespace {
     52 
     53 class 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 
    105 TEST_VIEW(ToolbarButtonTest, button_)
    106 
    107 TEST_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 
    135 TEST_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 
    151 TEST_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 
    169 TEST_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 
    192 TEST_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 
    211 TEST_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 
    224 TEST_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 
    237 TEST_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 
    265 TEST_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 
    286 TEST_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