summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshinyak@google.com <shinyak@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-23 07:45:11 +0000
committershinyak@google.com <shinyak@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-23 07:45:11 +0000
commitf55962f2f0cf52a6a878d0bc574c5975d646d265 (patch)
tree4ab23c675e5d71bf59acf74624f09880f66fc0d6
parent334749a11083fc523b9abab456ecca2072cd2055 (diff)
downloadchromium_src-f55962f2f0cf52a6a878d0bc574c5975d646d265.zip
chromium_src-f55962f2f0cf52a6a878d0bc574c5975d646d265.tar.gz
chromium_src-f55962f2f0cf52a6a878d0bc574c5975d646d265.tar.bz2
Added right click handler to back/forward button on Mac Chromium.
BUG=62620 TEST=Right click on the back/forward button in the toolbar and investigate that a menu is shown. Review URL: http://codereview.chromium.org/7104020 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93793 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/ui/cocoa/menu_button.h4
-rw-r--r--chrome/browser/ui/cocoa/menu_button.mm16
-rw-r--r--chrome/browser/ui/cocoa/menu_button_unittest.mm71
-rw-r--r--chrome/browser/ui/cocoa/toolbar/toolbar_button.h5
-rw-r--r--chrome/browser/ui/cocoa/toolbar/toolbar_button.mm77
-rw-r--r--chrome/browser/ui/cocoa/toolbar/toolbar_button_unittest.mm54
-rw-r--r--chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm3
7 files changed, 143 insertions, 87 deletions
diff --git a/chrome/browser/ui/cocoa/menu_button.h b/chrome/browser/ui/cocoa/menu_button.h
index cca74ab..bc12be8 100644
--- a/chrome/browser/ui/cocoa/menu_button.h
+++ b/chrome/browser/ui/cocoa/menu_button.h
@@ -28,6 +28,7 @@
scoped_nsobject<NSMenu> attachedMenu_;
BOOL attachedMenuEnabled_;
BOOL openMenuOnClick_;
+ BOOL openMenuOnRightClick_;
scoped_nsobject<NSPopUpButtonCell> popUpCell_;
}
@@ -43,6 +44,9 @@
// menu will only be opened when clicked and held.
@property(assign, nonatomic) BOOL openMenuOnClick;
+// Whether or not to open the menu when the right button is clicked.
+@property(assign, nonatomic) BOOL openMenuOnRightClick;
+
// Returns the rectangle that menus are anchored at. Can be overridden by
// subclasses, returns -bounds by default.
- (NSRect)menuRect;
diff --git a/chrome/browser/ui/cocoa/menu_button.mm b/chrome/browser/ui/cocoa/menu_button.mm
index 92b4c49..8cc0812 100644
--- a/chrome/browser/ui/cocoa/menu_button.mm
+++ b/chrome/browser/ui/cocoa/menu_button.mm
@@ -18,6 +18,7 @@
@implementation MenuButton
@synthesize openMenuOnClick = openMenuOnClick_;
+@synthesize openMenuOnRightClick = openMenuOnRightClick_;
// Overrides:
@@ -57,6 +58,15 @@
[self configureCell];
}
+- (void)rightMouseDown:(NSEvent*)theEvent {
+ if (!openMenuOnRightClick_) {
+ [super rightMouseDown:theEvent];
+ return;
+ }
+
+ [self clickShowMenu:self];
+}
+
// Accessors and mutators:
- (NSMenu*)attachedMenu {
@@ -79,6 +89,10 @@
}
}
+- (void)setOpenMenuOnRightClick:(BOOL)enabled {
+ openMenuOnRightClick_ = enabled;
+}
+
- (NSRect)menuRect {
return [self bounds];
}
@@ -155,7 +169,7 @@
- (void)clickShowMenu:(id)sender {
// This should only be called if openMenuOnClick has been set (which hooks
// up this target-action).
- DCHECK(openMenuOnClick_);
+ DCHECK(openMenuOnClick_ || openMenuOnRightClick_);
[self showMenu:NO];
}
diff --git a/chrome/browser/ui/cocoa/menu_button_unittest.mm b/chrome/browser/ui/cocoa/menu_button_unittest.mm
index 98a03e9..be8a3e4 100644
--- a/chrome/browser/ui/cocoa/menu_button_unittest.mm
+++ b/chrome/browser/ui/cocoa/menu_button_unittest.mm
@@ -79,6 +79,23 @@ class MenuButtonTest : public CocoaTest {
return menu;
}
+ NSEvent* MouseDownEvent(NSEventType eventType) {
+ NSPoint location;
+ location.x = location.y = 0;
+ NSGraphicsContext* context = [NSGraphicsContext currentContext];
+ NSEvent* event = [NSEvent mouseEventWithType:eventType
+ location:location
+ modifierFlags:0
+ timestamp:0
+ windowNumber:0
+ context:context
+ eventNumber:0
+ clickCount:1
+ pressure:0.0F];
+
+ return event;
+ }
+
MenuButton* button_;
};
@@ -115,4 +132,58 @@ TEST_F(MenuButtonTest, OpenOnClick) {
EXPECT_FALSE([delegate isOpen]);
}
+TEST_F(MenuButtonTest, OpenOnRightClick) {
+ scoped_nsobject<NSMenu> menu(CreateMenu());
+ ASSERT_TRUE(menu.get());
+
+ scoped_nsobject<MenuButtonTestDelegate> delegate(
+ [[MenuButtonTestDelegate alloc] initWithMenu:menu.get()]);
+ ASSERT_TRUE(delegate.get());
+
+ [menu setDelegate:delegate.get()];
+ [button_ setAttachedMenu:menu];
+ [button_ setOpenMenuOnClick:YES];
+ // Right click is enabled.
+ [button_ setOpenMenuOnRightClick:YES];
+
+ EXPECT_FALSE([delegate isOpen]);
+ EXPECT_FALSE([delegate didOpen]);
+
+ // Should open the menu.
+ NSEvent* event = MouseDownEvent(NSRightMouseDown);
+ [button_ rightMouseDown:event];
+
+ EXPECT_TRUE([delegate didOpen]);
+ EXPECT_FALSE([delegate isOpen]);
+}
+
+TEST_F(MenuButtonTest, DontOpenOnRightClickWithoutSetRightClick) {
+ scoped_nsobject<NSMenu> menu(CreateMenu());
+ ASSERT_TRUE(menu.get());
+
+ scoped_nsobject<MenuButtonTestDelegate> delegate(
+ [[MenuButtonTestDelegate alloc] initWithMenu:menu.get()]);
+ ASSERT_TRUE(delegate.get());
+
+ [menu setDelegate:delegate.get()];
+ [button_ setAttachedMenu:menu];
+ [button_ setOpenMenuOnClick:YES];
+
+ EXPECT_FALSE([delegate isOpen]);
+ EXPECT_FALSE([delegate didOpen]);
+
+ // Should not open the menu.
+ NSEvent* event = MouseDownEvent(NSRightMouseDown);
+ [button_ rightMouseDown:event];
+
+ EXPECT_FALSE([delegate didOpen]);
+ EXPECT_FALSE([delegate isOpen]);
+
+ // Should open the menu in this case.
+ [button_ performClick:nil];
+
+ EXPECT_TRUE([delegate didOpen]);
+ EXPECT_FALSE([delegate isOpen]);
+}
+
} // namespace
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_button.h b/chrome/browser/ui/cocoa/toolbar/toolbar_button.h
index c35d1e5..3a7f1b6 100644
--- a/chrome/browser/ui/cocoa/toolbar/toolbar_button.h
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_button.h
@@ -14,11 +14,6 @@
@protected
// YES when middle mouse clicks should be handled.
BOOL handleMiddleClick_;
-
- // YES when a middle mouse click is being handled. This is set to YES by an
- // NSOtherMouseDown event, and NO by an NSOtherMouseUp event. While this is
- // YES, other mouse button events should be ignored.
- BOOL handlingMiddleClick_;
}
// Whether or not to handle the mouse middle click events.
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_button.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_button.mm
index 517e6e5..afc3483 100644
--- a/chrome/browser/ui/cocoa/toolbar/toolbar_button.mm
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_button.mm
@@ -4,63 +4,42 @@
#import "chrome/browser/ui/cocoa/toolbar/toolbar_button.h"
-@interface ToolbarButton (Private)
-- (BOOL)updateStatus:(NSEvent*)theEvent;
-@end
-
@implementation ToolbarButton
@synthesize handleMiddleClick = handleMiddleClick_;
-- (void)mouseDown:(NSEvent*)theEvent {
- if (!handlingMiddleClick_)
- [super mouseDown:theEvent];
-}
-
-- (void)mouseDragged:(NSEvent*)theEvent {
- if (!handlingMiddleClick_)
- [super mouseDragged:theEvent];
-}
-
-- (void)mouseUp:(NSEvent*)theEvent {
- if (!handlingMiddleClick_)
- [super mouseUp:theEvent];
-}
-
- (void)otherMouseDown:(NSEvent*)theEvent {
- if (![self shouldHandleEvent:theEvent])
+ if (![self shouldHandleEvent:theEvent]) {
[super otherMouseDown:theEvent];
- else
- handlingMiddleClick_ = [self updateStatus:theEvent];
-}
-
-- (void)otherMouseDragged:(NSEvent*)theEvent {
- if (!handlingMiddleClick_ || ![self shouldHandleEvent:theEvent])
- [super otherMouseDragged:theEvent];
- else
- [self updateStatus:theEvent];
-}
-
-- (void)otherMouseUp:(NSEvent*)theEvent {
- if (!handlingMiddleClick_ || ![self shouldHandleEvent:theEvent]) {
- [super otherMouseUp:theEvent];
- } else {
- if ([self state] == NSOnState)
- [self sendAction:[self action] to:[self target]];
-
- [self setState:NSOffState];
- [self highlight:NO];
- handlingMiddleClick_ = NO;
+ return;
}
-}
-- (BOOL)updateStatus:(NSEvent*)theEvent {
- NSPoint mouseLoc = [self convertPoint:[theEvent locationInWindow]
- fromView:nil];
- BOOL isInside = [self mouse:mouseLoc inRect:[self bounds]];
- [self setState:isInside ? NSOnState : NSOffState];
- [self highlight:isInside];
- return isInside;
+ NSEvent* nextEvent = theEvent;
+ BOOL isInside;
+
+ // Loop until middle button is released. Also, the mouse cursor is outside of
+ // the button, the button should not be highlighted.
+ do {
+ NSPoint mouseLoc = [self convertPoint:[nextEvent locationInWindow]
+ fromView:nil];
+ isInside = [self mouse:mouseLoc inRect:[self bounds]];
+ [self highlight:isInside];
+ [self setState:isInside ? NSOnState : NSOffState];
+
+ NSUInteger mask = NSOtherMouseDraggedMask | NSOtherMouseUpMask;
+ nextEvent = [[self window] nextEventMatchingMask:mask];
+ } while (!([nextEvent buttonNumber] == 2 &&
+ [nextEvent type] == NSOtherMouseUp));
+
+ // Discard the events before the middle button up event.
+ // If we don't discard it, the events will be re-processed later.
+ [[self window] discardEventsMatchingMask:NSAnyEventMask
+ beforeEvent:nextEvent];
+
+ [self highlight:NO];
+ [self setState:NSOffState];
+ if (isInside)
+ [self sendAction:[self action] to:[self target]];
}
- (BOOL)shouldHandleEvent:(NSEvent*)theEvent {
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_button_unittest.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_button_unittest.mm
index 3322267..b7907a3 100644
--- a/chrome/browser/ui/cocoa/toolbar/toolbar_button_unittest.mm
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_button_unittest.mm
@@ -213,9 +213,9 @@ TEST_F(ToolbarButtonTest, MouseClickInsideOnYES) {
[button_ setHandleMiddleClick:YES];
// Middle button clicking in the view.
+ [NSApp postEvent:other_up_in_view atStart:YES];
[button_ otherMouseDown:other_down_in_view];
- EXPECT_EQ(NSOnState, [button_ state]);
- [button_ otherMouseUp:other_up_in_view];
+
EXPECT_EQ(NSOffState, [button_ state]);
EXPECT_EQ(1, [button_ numOfClick]);
EXPECT_EQ(IDC_HOME, [button_ lastCommand]);
@@ -226,9 +226,9 @@ TEST_F(ToolbarButtonTest, MouseClickOutsideOnYES) {
[button_ setHandleMiddleClick:YES];
// Middle button clicking outside of the view.
+ [NSApp postEvent:other_up_out_view atStart:YES];
[button_ otherMouseDown:other_down_out_view];
- EXPECT_EQ(NSOffState, [button_ state]);
- [button_ otherMouseUp:other_up_out_view];
+
EXPECT_EQ(NSOffState, [button_ state]);
EXPECT_EQ(0, [button_ numOfClick]);
EXPECT_EQ(IDC_STOP, [button_ lastCommand]);
@@ -239,45 +239,36 @@ TEST_F(ToolbarButtonTest, MouseDraggingOnYES) {
[button_ setHandleMiddleClick:YES];
// Middle button being down in the view and up outside of the view.
+ [NSApp postEvent:other_up_out_view atStart:YES];
+ [NSApp postEvent:other_dragged_out_view atStart:YES];
[button_ otherMouseDown:other_down_in_view];
- EXPECT_EQ(NSOnState, [button_ state]);
- [button_ otherMouseDragged:other_dragged_out_view];
- EXPECT_EQ(NSOffState, [button_ state]);
- [button_ otherMouseUp:other_up_out_view];
+
EXPECT_EQ(NSOffState, [button_ state]);
EXPECT_EQ(0, [button_ numOfClick]);
EXPECT_EQ(IDC_STOP, [button_ lastCommand]);
// Middle button being down on the button, move to outside and move on it
// again, then up on the button.
+ [NSApp postEvent:other_up_in_view atStart:YES];
+ [NSApp postEvent:other_dragged_in_view atStart:YES];
+ [NSApp postEvent:other_dragged_out_view atStart:YES];
[button_ otherMouseDown:other_down_in_view];
- EXPECT_EQ(NSOnState, [button_ state]);
- [button_ otherMouseDragged:other_dragged_out_view];
- EXPECT_EQ(NSOffState, [button_ state]);
- [button_ otherMouseDragged:other_dragged_in_view];
- EXPECT_EQ(NSOnState, [button_ state]);
- [button_ otherMouseUp:other_up_in_view];
+
EXPECT_EQ(NSOffState, [button_ state]);
EXPECT_EQ(1, [button_ numOfClick]);
EXPECT_EQ(IDC_HOME, [button_ lastCommand]);
}
-TEST_F(ToolbarButtonTest, DoesNotSwallowRightClickOnYES) {
+TEST_F(ToolbarButtonTest, DoesSwallowRightClickOnYES) {
// Enable middle button handling.
[button_ setHandleMiddleClick:YES];
- // Middle button being down should swallow right button clicks, but
- // ToolbarButton doesn't swallow it because it doesn't handle right button
- // events.
+ // Middle button being down should swallow right button clicks.
+ [NSApp postEvent:other_up_in_view atStart:YES];
+ [NSApp postEvent:right_up_in_view atStart:YES];
+ [NSApp postEvent:right_down_in_view atStart:YES];
[button_ otherMouseDown:other_down_in_view];
- EXPECT_EQ(NSOnState, [button_ state]);
- [button_ rightMouseDown:right_down_in_view];
- EXPECT_EQ(NSOnState, [button_ state]);
- [button_ rightMouseUp:right_up_in_view];
- EXPECT_EQ(NSOnState, [button_ state]);
- EXPECT_EQ(0, [button_ numOfClick]);
- EXPECT_EQ(IDC_STOP, [button_ lastCommand]);
- [button_ otherMouseUp:other_up_in_view];
+
EXPECT_EQ(NSOffState, [button_ state]);
EXPECT_EQ(1, [button_ numOfClick]);
EXPECT_EQ(IDC_HOME, [button_ lastCommand]);
@@ -288,13 +279,12 @@ TEST_F(ToolbarButtonTest, DoesSwallowLeftClickOnYES) {
[button_ setHandleMiddleClick:YES];
// Middle button being down swallows left button clicks.
- [button_ otherMouseDown:other_down_in_view];
- EXPECT_EQ(NSOnState, [button_ state]);
+ [NSApp postEvent:other_up_in_view atStart:YES];
[NSApp postEvent:left_up_in_view atStart:YES];
- [button_ mouseDown:left_down_in_view];
- EXPECT_EQ(0, [button_ numOfClick]);
- EXPECT_EQ(IDC_STOP, [button_ lastCommand]);
- [button_ otherMouseUp:other_up_in_view];
+ [NSApp postEvent:left_down_in_view atStart:YES];
+ [button_ otherMouseDown:other_down_in_view];
+
+ EXPECT_EQ(NSOffState, [button_ state]);
EXPECT_EQ(1, [button_ numOfClick]);
EXPECT_EQ(IDC_HOME, [button_ lastCommand]);
}
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm
index 7044bcc..4d3ee82 100644
--- a/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm
+++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller.mm
@@ -265,6 +265,9 @@ class NotificationBridge : public NotificationObserver {
[wrenchButton_ setOpenMenuOnClick:YES];
+ [backButton_ setOpenMenuOnRightClick:YES];
+ [forwardButton_ setOpenMenuOnRightClick:YES];
+
[backButton_ setHandleMiddleClick:YES];
[forwardButton_ setHandleMiddleClick:YES];
[reloadButton_ setHandleMiddleClick:YES];