Commit 8b0fd02a authored by lgrey's avatar lgrey Committed by Commit bot

[Mac] Flip toolbar in RTL

Browser actions will be reordered in a future change.

BUG=648558, 648563, 673362

Review-Url: https://codereview.chromium.org/2607533004
Cr-Commit-Position: refs/heads/master@{#441925}
parent 5d044bb4
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <algorithm> #include <algorithm>
#include <utility> #include <utility>
#import "chrome/browser/ui/cocoa/l10n_util.h"
#import "chrome/browser/ui/cocoa/view_id_util.h" #import "chrome/browser/ui/cocoa/view_id_util.h"
#include "ui/base/cocoa/appkit_utils.h" #include "ui/base/cocoa/appkit_utils.h"
#include "ui/events/keycodes/keyboard_code_conversion_mac.h" #include "ui/events/keycodes/keyboard_code_conversion_mac.h"
...@@ -58,6 +59,9 @@ const CGFloat kMinimumContainerWidth = 3.0; ...@@ -58,6 +59,9 @@ const CGFloat kMinimumContainerWidth = 3.0;
- (id)initWithFrame:(NSRect)frameRect { - (id)initWithFrame:(NSRect)frameRect {
if ((self = [super initWithFrame:frameRect])) { if ((self = [super initWithFrame:frameRect])) {
grippyRect_ = NSMakeRect(0.0, 0.0, kGrippyWidth, NSHeight([self bounds])); grippyRect_ = NSMakeRect(0.0, 0.0, kGrippyWidth, NSHeight([self bounds]));
if (cocoa_l10n_util::ShouldDoExperimentalRTLLayout())
grippyRect_.origin.x = NSWidth(frameRect) - NSWidth(grippyRect_);
canDragLeft_ = YES; canDragLeft_ = YES;
canDragRight_ = YES; canDragRight_ = YES;
resizable_ = YES; resizable_ = YES;
...@@ -162,6 +166,8 @@ const CGFloat kMinimumContainerWidth = 3.0; ...@@ -162,6 +166,8 @@ const CGFloat kMinimumContainerWidth = 3.0;
} }
- (void)resetCursorRects { - (void)resetCursorRects {
if (cocoa_l10n_util::ShouldDoExperimentalRTLLayout())
grippyRect_.origin.x = NSWidth([self frame]) - NSWidth(grippyRect_);
[self addCursorRect:grippyRect_ cursor:[self appropriateCursorForGrippy]]; [self addCursorRect:grippyRect_ cursor:[self appropriateCursorForGrippy]];
} }
...@@ -214,23 +220,29 @@ const CGFloat kMinimumContainerWidth = 3.0; ...@@ -214,23 +220,29 @@ const CGFloat kMinimumContainerWidth = 3.0;
NSRect containerFrame = [self frame]; NSRect containerFrame = [self frame];
CGFloat dX = [theEvent deltaX]; CGFloat dX = [theEvent deltaX];
CGFloat withDelta = location.x - dX; CGFloat withDelta = location.x - dX;
canDragRight_ = (withDelta >= initialDragPoint_.x) && BOOL isRTL = cocoa_l10n_util::ShouldDoExperimentalRTLLayout();
(NSWidth(containerFrame) > kMinimumContainerWidth);
CGFloat maxAllowedWidth = [self maxAllowedWidth]; CGFloat maxAllowedWidth = [self maxAllowedWidth];
containerFrame.size.width =
std::max(NSWidth(containerFrame) - dX, kMinimumContainerWidth);
canDragLeft_ = withDelta <= initialDragPoint_.x &&
NSWidth(containerFrame) < maxDesiredWidth_ &&
NSWidth(containerFrame) < maxAllowedWidth;
if ((dX < 0.0 && !canDragLeft_) || (dX > 0.0 && !canDragRight_)) const CGFloat maxWidth = std::min(maxAllowedWidth, maxDesiredWidth_);
return; CGFloat newWidth = NSWidth(containerFrame) + (isRTL ? dX : -dX);
newWidth = std::min(std::max(newWidth, kMinimumContainerWidth), maxWidth);
if (NSWidth(containerFrame) <= kMinimumContainerWidth) BOOL canGrow = NSWidth(containerFrame) < maxWidth;
BOOL canShrink = NSWidth(containerFrame) > kMinimumContainerWidth;
canDragLeft_ =
withDelta <= initialDragPoint_.x && (isRTL ? canShrink : canGrow);
canDragRight_ =
(withDelta >= initialDragPoint_.x) && (isRTL ? canGrow : canShrink);
if ((dX < 0.0 && !canDragLeft_) || (dX > 0.0 && !canDragRight_) ||
fabs(dX) < FLT_EPSILON)
return; return;
grippyPinned_ = NSWidth(containerFrame) >= maxAllowedWidth; grippyPinned_ = newWidth >= maxAllowedWidth;
if (!isRTL)
containerFrame.origin.x += dX; containerFrame.origin.x += dX;
containerFrame.size.width = newWidth;
[self setFrame:containerFrame]; [self setFrame:containerFrame];
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
...@@ -271,14 +283,18 @@ const CGFloat kMinimumContainerWidth = 3.0; ...@@ -271,14 +283,18 @@ const CGFloat kMinimumContainerWidth = 3.0;
- (void)resizeToWidth:(CGFloat)width animate:(BOOL)animate { - (void)resizeToWidth:(CGFloat)width animate:(BOOL)animate {
width = std::max(width, kMinimumContainerWidth); width = std::max(width, kMinimumContainerWidth);
NSRect frame = [self frame]; NSRect newFrame = [self frame];
CGFloat maxAllowedWidth = [self maxAllowedWidth]; CGFloat maxAllowedWidth = [self maxAllowedWidth];
width = std::min(maxAllowedWidth, width); width = std::min(maxAllowedWidth, width);
CGFloat dX = frame.size.width - width; if (cocoa_l10n_util::ShouldDoExperimentalRTLLayout()) {
frame.size.width = width; newFrame.size.width = width;
NSRect newFrame = NSOffsetRect(frame, dX, 0); } else {
CGFloat dX = NSWidth(newFrame) - width;
newFrame.size.width = width;
newFrame.origin.x += dX;
}
grippyPinned_ = width == maxAllowedWidth; grippyPinned_ = width == maxAllowedWidth;
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#import "chrome/browser/ui/cocoa/extensions/extension_popup_controller.h" #import "chrome/browser/ui/cocoa/extensions/extension_popup_controller.h"
#import "chrome/browser/ui/cocoa/extensions/toolbar_actions_bar_bubble_mac.h" #import "chrome/browser/ui/cocoa/extensions/toolbar_actions_bar_bubble_mac.h"
#import "chrome/browser/ui/cocoa/image_button_cell.h" #import "chrome/browser/ui/cocoa/image_button_cell.h"
#import "chrome/browser/ui/cocoa/l10n_util.h"
#import "chrome/browser/ui/cocoa/menu_button.h" #import "chrome/browser/ui/cocoa/menu_button.h"
#import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h" #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
#include "chrome/browser/ui/extensions/extension_message_bubble_bridge.h" #include "chrome/browser/ui/extensions/extension_message_bubble_bridge.h"
...@@ -581,11 +582,14 @@ void ToolbarActionsBarBridge::ShowToolbarActionBubble( ...@@ -581,11 +582,14 @@ void ToolbarActionsBarBridge::ShowToolbarActionBubble(
if (NSMinX([button frameAfterAnimation]) == NSMinX(buttonFrame)) if (NSMinX([button frameAfterAnimation]) == NSMinX(buttonFrame))
continue; continue;
// We set the x-origin by calculating the proper distance from the right // In LTR, We set the x-origin by calculating the proper distance from the
// edge in the container so that, if the container is animating, the // right edge in the container so that, if the container is animating, the
// button appears stationary. // button appears stationary.
if (!cocoa_l10n_util::ShouldDoExperimentalRTLLayout()) {
buttonFrame.origin.x = NSWidth([containerView_ frame]) - buttonFrame.origin.x = NSWidth([containerView_ frame]) -
(toolbarActionsBar_->GetPreferredSize().width() - NSMinX(buttonFrame)); (toolbarActionsBar_->GetPreferredSize().width() -
NSMinX(buttonFrame));
}
[button setFrame:buttonFrame animate:NO]; [button setFrame:buttonFrame animate:NO];
} }
} }
...@@ -783,9 +787,16 @@ void ToolbarActionsBarBridge::ShowToolbarActionBubble( ...@@ -783,9 +787,16 @@ void ToolbarActionsBarBridge::ShowToolbarActionBubble(
} }
- (void)updateGrippyCursors { - (void)updateGrippyCursors {
BOOL canClose = [self visibleButtonCount] > 0;
BOOL canOpen = toolbarActionsBar_->GetIconCount() != [buttons_ count];
[containerView_
setCanDragLeft:cocoa_l10n_util::ShouldDoExperimentalRTLLayout()
? canClose
: canOpen];
[containerView_ [containerView_
setCanDragLeft:toolbarActionsBar_->GetIconCount() != [buttons_ count]]; setCanDragRight:cocoa_l10n_util::ShouldDoExperimentalRTLLayout()
[containerView_ setCanDragRight:[self visibleButtonCount] > 0]; ? canOpen
: canClose];
[[containerView_ window] invalidateCursorRectsForView:containerView_]; [[containerView_ window] invalidateCursorRectsForView:containerView_];
} }
......
...@@ -200,6 +200,10 @@ class NotificationBridge; ...@@ -200,6 +200,10 @@ class NotificationBridge;
- (void)installAppMenu; - (void)installAppMenu;
// Return a hover button for the current event. // Return a hover button for the current event.
- (NSButton*)hoverButtonForEvent:(NSEvent*)theEvent; - (NSButton*)hoverButtonForEvent:(NSEvent*)theEvent;
// Adjusts browser actions container view in response to toolbar frame changes.
// Outside of tests, called in response to frame changed/new window
// notifications.
- (void)toolbarFrameChanged;
@end @end
#endif // CHROME_BROWSER_UI_COCOA_TOOLBAR_TOOLBAR_CONTROLLER_H_ #endif // CHROME_BROWSER_UI_COCOA_TOOLBAR_TOOLBAR_CONTROLLER_H_
...@@ -4,25 +4,34 @@ ...@@ -4,25 +4,34 @@
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#include "base/command_line.h"
#import "base/mac/scoped_nsobject.h" #import "base/mac/scoped_nsobject.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "chrome/app/chrome_command_ids.h" #include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/command_updater.h" #include "chrome/browser/command_updater.h"
#include "chrome/browser/extensions/extension_action_test_util.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_command_controller.h" #include "chrome/browser/ui/browser_command_controller.h"
#include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_list_observer.h" #include "chrome/browser/ui/browser_list_observer.h"
#import "chrome/browser/ui/cocoa/image_button_cell.h" #import "chrome/browser/ui/cocoa/image_button_cell.h"
#import "chrome/browser/ui/cocoa/extensions/browser_actions_controller.h"
#import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h" #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
#import "chrome/browser/ui/cocoa/location_bar/translate_decoration.h" #import "chrome/browser/ui/cocoa/location_bar/translate_decoration.h"
#include "chrome/browser/ui/cocoa/test/cocoa_profile_test.h" #include "chrome/browser/ui/cocoa/test/cocoa_profile_test.h"
#include "chrome/browser/ui/cocoa/test/scoped_force_rtl_mac.h"
#import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h" #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
#include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
#include "chrome/browser/ui/toolbar/toolbar_actions_model.h"
#import "chrome/browser/ui/cocoa/view_resizer_pong.h" #import "chrome/browser/ui/cocoa/view_resizer_pong.h"
#include "chrome/common/pref_names.h" #include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
#include "extensions/browser/extension_system.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#import "testing/gtest_mac.h" #import "testing/gtest_mac.h"
#include "testing/platform_test.h" #include "testing/platform_test.h"
...@@ -74,14 +83,37 @@ class ToolbarControllerTest : public CocoaProfileTest { ...@@ -74,14 +83,37 @@ class ToolbarControllerTest : public CocoaProfileTest {
// Indexes that match the ordering returned by the private ToolbarController // Indexes that match the ordering returned by the private ToolbarController
// |-toolbarViews| method. // |-toolbarViews| method.
enum SubviewIndex { enum SubviewIndex {
kBackIndex, kForwardIndex, kReloadIndex, kHomeIndex, kBackIndex,
kAppMenuIndex, kLocationIndex, kBrowserActionContainerViewIndex kForwardIndex,
kReloadIndex,
kHomeIndex,
kLocationIndex,
kBrowserActionContainerViewIndex,
kAppMenuIndex
}; };
void SetUp() override { void SetUp() override {
CocoaProfileTest::SetUp(); CocoaProfileTest::SetUp();
ASSERT_TRUE(browser()); ASSERT_TRUE(browser());
// Add an extension so the browser action container view
// is visible and has a real size/position.
extensions::TestExtensionSystem* extension_system =
static_cast<extensions::TestExtensionSystem*>(
extensions::ExtensionSystem::Get(profile()));
extension_system->CreateExtensionService(
base::CommandLine::ForCurrentProcess(), base::FilePath(), false);
scoped_refptr<const extensions::Extension> extension =
extensions::extension_action_test_util::CreateActionExtension(
"ABC", extensions::extension_action_test_util::BROWSER_ACTION);
extensions::ExtensionSystem::Get(profile())
->extension_service()
->AddExtension(extension.get());
ToolbarActionsModel* model =
extensions::extension_action_test_util::CreateToolbarModelForProfile(
profile());
model->SetVisibleIconCount(1);
resizeDelegate_.reset([[ViewResizerPong alloc] init]); resizeDelegate_.reset([[ViewResizerPong alloc] init]);
CommandUpdater* updater = CommandUpdater* updater =
...@@ -98,6 +130,12 @@ class ToolbarControllerTest : public CocoaProfileTest { ...@@ -98,6 +130,12 @@ class ToolbarControllerTest : public CocoaProfileTest {
EXPECT_TRUE([bar_ view]); EXPECT_TRUE([bar_ view]);
NSView* parent = [test_window() contentView]; NSView* parent = [test_window() contentView];
[parent addSubview:[bar_ view]]; [parent addSubview:[bar_ view]];
// Nudge a few things to ensure the browser actions container gets
// laid out.
[bar_ createBrowserActionButtons];
[[bar_ browserActionsController] update];
[bar_ toolbarFrameChanged];
} }
void TearDown() override { void TearDown() override {
...@@ -177,7 +215,7 @@ TEST_F(ToolbarControllerTest, UpdateVisibility) { ...@@ -177,7 +215,7 @@ TEST_F(ToolbarControllerTest, UpdateVisibility) {
EXPECT_FALSE([GetSubviewAt(kReloadIndex) isHidden]); EXPECT_FALSE([GetSubviewAt(kReloadIndex) isHidden]);
EXPECT_FALSE([GetSubviewAt(kAppMenuIndex) isHidden]); EXPECT_FALSE([GetSubviewAt(kAppMenuIndex) isHidden]);
EXPECT_TRUE([GetSubviewAt(kHomeIndex) isHidden]); EXPECT_TRUE([GetSubviewAt(kHomeIndex) isHidden]);
EXPECT_TRUE([GetSubviewAt(kBrowserActionContainerViewIndex) isHidden]); EXPECT_FALSE([GetSubviewAt(kBrowserActionContainerViewIndex) isHidden]);
// For NO/NO, only the top level toolbar view is hidden. // For NO/NO, only the top level toolbar view is hidden.
[bar_ setHasToolbar:NO hasLocationBar:NO]; [bar_ setHasToolbar:NO hasLocationBar:NO];
...@@ -188,7 +226,7 @@ TEST_F(ToolbarControllerTest, UpdateVisibility) { ...@@ -188,7 +226,7 @@ TEST_F(ToolbarControllerTest, UpdateVisibility) {
EXPECT_FALSE([GetSubviewAt(kReloadIndex) isHidden]); EXPECT_FALSE([GetSubviewAt(kReloadIndex) isHidden]);
EXPECT_FALSE([GetSubviewAt(kAppMenuIndex) isHidden]); EXPECT_FALSE([GetSubviewAt(kAppMenuIndex) isHidden]);
EXPECT_TRUE([GetSubviewAt(kHomeIndex) isHidden]); EXPECT_TRUE([GetSubviewAt(kHomeIndex) isHidden]);
EXPECT_TRUE([GetSubviewAt(kBrowserActionContainerViewIndex) isHidden]); EXPECT_FALSE([GetSubviewAt(kBrowserActionContainerViewIndex) isHidden]);
// Now test the inescapable state. // Now test the inescapable state.
[bar_ setHasToolbar:NO hasLocationBar:YES]; [bar_ setHasToolbar:NO hasLocationBar:YES];
...@@ -391,6 +429,36 @@ TEST_F(ToolbarControllerTest, HoverButtonForEvent) { ...@@ -391,6 +429,36 @@ TEST_F(ToolbarControllerTest, HoverButtonForEvent) {
[bar_ setView:toolbarView]; [bar_ setView:toolbarView];
} }
// Test that subviews are ordered left to right
TEST_F(ToolbarControllerTest, ElementOrder) {
NSArray* views = [bar_ toolbarViews];
for (size_t i = 1; i < [views count]; i++) {
NSView* previousSubview = views[i - 1];
NSView* subview = views[i];
EXPECT_LE(NSMinX([previousSubview frame]), NSMinX([subview frame]));
}
}
class ToolbarControllerRTLTest : public ToolbarControllerTest {
public:
ToolbarControllerRTLTest() {}
private:
cocoa_l10n_util::ScopedForceRTLMac rtl_;
DISALLOW_COPY_AND_ASSIGN(ToolbarControllerRTLTest);
};
// Test that subviews are ordered right to left
TEST_F(ToolbarControllerRTLTest, ElementOrder) {
NSArray* views = [[[bar_ toolbarViews] reverseObjectEnumerator] allObjects];
for (size_t i = 1; i < [views count]; i++) {
NSView* previousSubview = views[i - 1];
NSView* subview = views[i];
EXPECT_LE(NSMinX([previousSubview frame]), NSMinX([subview frame]));
}
}
class BrowserRemovedObserver : public chrome::BrowserListObserver { class BrowserRemovedObserver : public chrome::BrowserListObserver {
public: public:
BrowserRemovedObserver() { BrowserList::AddObserver(this); } BrowserRemovedObserver() { BrowserList::AddObserver(this); }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment