Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(407)

Unified Diff: chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm

Issue 2171473002: Bringing back fast user switching on Mac material design user menu (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Final nits Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm
diff --git a/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm b/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm
index d263e6c1f57d2cf38b7cdf052582849c445279a5..2b8dbf2e385f24fcc263f5e6a2abb4d259376a46 100644
--- a/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm
+++ b/chrome/browser/ui/cocoa/profiles/profile_chooser_controller.mm
@@ -34,6 +34,7 @@
#include "chrome/browser/signin/signin_ui_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/chrome_style.h"
@@ -74,8 +75,12 @@
#include "ui/base/l10n/l10n_util_mac.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/gfx/color_palette.h"
#include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_skia_util_mac.h"
+#include "ui/gfx/paint_vector_icon.h"
#include "ui/gfx/text_elider.h"
+#include "ui/gfx/vector_icons_public.h"
#include "ui/native_theme/common_theme.h"
#include "ui/native_theme/native_theme.h"
#include "ui/native_theme/native_theme_mac.h"
@@ -427,10 +432,14 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
int leftMarginSpacing_;
// Spacing between the cell image and title.
int imageTitleSpacing_;
+ // Padding added to the right margin of the button.
+ int rightMarginSpacing_;
}
- (id)initWithLeftMarginSpacing:(int)leftMarginSpacing
imageTitleSpacing:(int)imageTitleSpacing;
+
+- (void)setRightMarginSpacing:(int)rightMarginSpacing;
@end
@implementation CustomPaddingImageButtonCell
@@ -443,6 +452,10 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
return self;
}
+- (void)setRightMarginSpacing:(int)rightMarginSpacing {
+ rightMarginSpacing_ = rightMarginSpacing;
+}
+
- (NSRect)drawTitle:(NSAttributedString*)title
withFrame:(NSRect)frame
inView:(NSView*)controlView {
@@ -454,6 +467,8 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
if ([self imagePosition] == NSImageLeft)
NSDivideRect(frame, &marginRect, &frame, imageTitleSpacing_, NSMinXEdge);
+ NSDivideRect(frame, &marginRect, &frame, rightMarginSpacing_, NSMaxXEdge);
+
return [super drawTitle:title withFrame:frame inView:controlView];
}
@@ -797,6 +812,8 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
base::scoped_nsobject<NSColor> backgroundColor_;
base::scoped_nsobject<NSColor> hoverColor_;
}
+
+- (void)setRightMarginSpacing:(int)rightMarginSpacing;
@end
@implementation BackgroundColorHoverButton
@@ -826,6 +843,10 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
return self;
}
+- (void)setRightMarginSpacing:(int)rightMarginSpacing {
+ [[self cell] setRightMarginSpacing:rightMarginSpacing];
+}
+
- (void)drawRect:(NSRect)dirtyRect {
if ([self isEnabled]) {
bool isHighlighted = ([self hoverState] != kHoverStateNone);
@@ -899,17 +920,21 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
- (CGFloat)addSeparatorToContainer:(NSView*)container
atYOffset:(CGFloat)yOffset;
-// Builds the right-click profile switcher.
-- (void)buildFastUserSwitcherViewWithProfiles:(NSMutableArray*)otherProfiles
- atYOffset:(CGFloat)yOffset
- inContainer:(NSView*)container;
+// Builds the fast user switcher view. In the current user menu, this is
+// triggered by right-clicking the avatar button; in the material design user
+// menu, this appears as part of the user menu. Returns the yOffset
+// corresponding to after the profile switcher buttons.
+- (CGFloat)buildFastUserSwitcherViewWithProfiles:(NSArray*)otherProfiles
+ atYOffset:(CGFloat)yOffset
+ inContainer:(NSView*)container;
// Builds the regular profile chooser view.
- (void)buildProfileChooserViewWithProfileView:(NSView*)currentProfileView
tutorialView:(NSView*)tutorialView
+ otherProfiles:(NSArray*)otherProfiles
atYOffset:(CGFloat)yOffset
inContainer:(NSView*)container
- displayLock:(bool)displayLock;
+ showLock:(bool)showLock;
// Builds the profile chooser view.
- (NSView*)buildProfileChooserView;
@@ -967,12 +992,17 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
- (NSView*)createGuestProfileView;
// Creates an item for the profile |itemIndex| that is used in the fast profile
-// switcher in the middle of the bubble.
+// switcher view.
- (NSButton*)createOtherProfileView:(int)itemIndex;
-// Creates the "Not you" and Lock option buttons.
+// Creates the following option buttons: lock profile, go incognito, and switch
+// user/exit guest.
- (NSView*)createOptionsViewWithRect:(NSRect)rect
- displayLock:(BOOL)displayLock;
+ showLock:(BOOL)showLock;
+// For material design user menu, creates the following option buttons: lock
+// profile/close all windows, switch user/exit guest, and open guest profile.
+- (NSView*)createMaterialDesignOptionsViewWithFrame:(NSRect)frame
+ showLock:(BOOL)showLock;
// Creates the account management view for the active profile.
- (NSView*)createCurrentProfileAccountsView:(NSRect)rect;
@@ -991,11 +1021,15 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
- (NSView*)buildSwitchUserView;
// Creates a button with |text| and |action|, optionally with an icon given by
-// |imageResourceId|.
+// |imageResourceId| or |image|.
- (NSButton*)hoverButtonWithRect:(NSRect)rect
text:(NSString*)text
imageResourceId:(int)imageResourceId
action:(SEL)action;
+- (NSButton*)hoverButtonWithRect:(NSRect)rect
+ text:(NSString*)text
+ image:(NSImage*)image
+ action:(SEL)action;
- (BackgroundColorHoverButton*)hoverButtonWithRect:(NSRect)rect
text:(NSString*)text
action:(SEL)action;
@@ -1040,6 +1074,13 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
ProfileMetrics::SWITCH_PROFILE_ICON);
}
+- (IBAction)switchToGuest:(id)sender {
+ PrefService* service = g_browser_process->local_state();
+ DCHECK(service);
+ DCHECK(service->GetBoolean(prefs::kBrowserGuestModeEnabled));
+ profiles::SwitchToGuestProfile(ProfileManager::CreateCallback());
+}
+
- (IBAction)showUserManager:(id)sender {
UserManager::Show(base::FilePath(),
profiles::USER_MANAGER_NO_TUTORIAL,
@@ -1056,6 +1097,10 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
profiles::CloseGuestProfileWindows();
}
+- (IBAction)closeAllWindows:(id)sender {
+ profiles::CloseProfileWindows(browser_->profile());
+}
+
- (IBAction)goIncognito:(id)sender {
DCHECK([self shouldShowGoIncognito]);
chrome::NewIncognitoWindow(browser_);
@@ -1339,33 +1384,52 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
// Builds the fast user switcher view in |container| at |yOffset| and populates
// it with the entries for every profile in |otherProfiles|. Returns the new
// yOffset after adding the elements.
-- (void)buildFastUserSwitcherViewWithProfiles:(NSMutableArray*)otherProfiles
- atYOffset:(CGFloat)yOffset
- inContainer:(NSView*)container {
+- (CGFloat)buildFastUserSwitcherViewWithProfiles:(NSArray*)otherProfiles
+ atYOffset:(CGFloat)yOffset
+ inContainer:(NSView*)container {
// Other profiles switcher. The profiles have already been sorted
// by their y-coordinate, so they can be added in the existing order.
for (NSView* otherProfileView in otherProfiles) {
- [otherProfileView setFrameOrigin:NSMakePoint(0, yOffset)];
- [container addSubview:otherProfileView];
- yOffset = NSMaxY([otherProfileView frame]);
+ [otherProfileView setFrameOrigin:NSMakePoint(0, yOffset)];
+ [container addSubview:otherProfileView];
+ yOffset = NSMaxY([otherProfileView frame]);
- yOffset = [self addSeparatorToContainer:container atYOffset: yOffset];
+ if (!switches::IsMaterialDesignUserMenu())
+ yOffset = [self addSeparatorToContainer:container atYOffset:yOffset];
}
[container setFrameSize:NSMakeSize(GetFixedMenuWidth(), yOffset)];
+ return yOffset;
}
- (void)buildProfileChooserViewWithProfileView:(NSView*)currentProfileView
tutorialView:(NSView*)tutorialView
+ otherProfiles:(NSArray*)otherProfiles
atYOffset:(CGFloat)yOffset
inContainer:(NSView*)container
- displayLock:(bool)displayLock {
+ showLock:(bool)showLock {
+ if (switches::IsMaterialDesignUserMenu())
+ yOffset += kRelatedControllVerticalSpacing;
+
// Option buttons.
NSRect rect = NSMakeRect(0, yOffset, GetFixedMenuWidth(), 0);
- NSView* optionsView = [self createOptionsViewWithRect:rect
- displayLock:displayLock];
+ NSView* optionsView =
+ switches::IsMaterialDesignUserMenu()
+ ? [self createMaterialDesignOptionsViewWithFrame:rect
+ showLock:showLock]
+ : [self createOptionsViewWithRect:rect showLock:showLock];
[container addSubview:optionsView];
rect.origin.y = NSMaxY([optionsView frame]);
+ yOffset = rect.origin.y;
+
+ // For material design user menu, add the fast user switching buttons.
+ if (switches::IsMaterialDesignUserMenu()) {
+ yOffset = [self buildFastUserSwitcherViewWithProfiles:otherProfiles
+ atYOffset:yOffset
+ inContainer:container];
+ yOffset += kRelatedControllVerticalSpacing;
+ rect.origin.y = yOffset;
+ }
NSBox* separator = [self horizontalSeparatorWithFrame:rect];
[container addSubview:separator];
@@ -1428,7 +1492,7 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
base::scoped_nsobject<NSMutableArray> otherProfiles(
[[NSMutableArray alloc] init]);
// Local and guest profiles cannot lock their profile.
- bool displayLock = false;
+ bool showLock = false;
bool isFastProfileChooser =
viewMode_ == profiles::BUBBLE_VIEW_MODE_FAST_PROFILE_CHOOSER;
if (isFastProfileChooser) {
@@ -1450,7 +1514,7 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
switches::IsMaterialDesignUserMenu()
? [self createMaterialDesignCurrentProfileView:item]
: [self createCurrentProfileView:item];
- displayLock = item.signed_in &&
+ showLock = item.signed_in &&
profiles::IsLockAvailable(browser_->profile());
} else {
[otherProfiles addObject:[self createOtherProfileView:i]];
@@ -1465,15 +1529,18 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
CGFloat yOffset = 1;
if (isFastProfileChooser) {
- [self buildFastUserSwitcherViewWithProfiles:otherProfiles.get()
- atYOffset:yOffset
- inContainer:container.get()];
+ if (!switches::IsMaterialDesignUserMenu()) {
+ [self buildFastUserSwitcherViewWithProfiles:otherProfiles.get()
+ atYOffset:yOffset
+ inContainer:container];
+ }
} else {
[self buildProfileChooserViewWithProfileView:currentProfileView
tutorialView:tutorialView
+ otherProfiles:otherProfiles.get()
atYOffset:yOffset
- inContainer:container.get()
- displayLock:displayLock];
+ inContainer:container
+ showLock:showLock];
}
return container.autorelease();
@@ -2082,23 +2149,39 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
NSRect rect = NSMakeRect(0, 0, GetFixedMenuWidth(),
kBlueButtonHeight + kSmallVerticalSpacing);
+ const int imageTitleSpacing = switches::IsMaterialDesignUserMenu()
+ ? kHorizontalSpacing
+ : kImageTitleSpacing;
base::scoped_nsobject<BackgroundColorHoverButton> profileButton(
[[BackgroundColorHoverButton alloc]
- initWithFrame:rect
- imageTitleSpacing:kImageTitleSpacing
- backgroundColor:GetDialogBackgroundColor()]);
+ initWithFrame:rect
+ imageTitleSpacing:imageTitleSpacing
+ backgroundColor:GetDialogBackgroundColor()]);
+ if (switches::IsMaterialDesignUserMenu())
+ [profileButton setRightMarginSpacing:kHorizontalSpacing];
NSString* title = base::SysUTF16ToNSString(
profiles::GetProfileSwitcherTextForItem(item));
[profileButton setTitle:title];
- // Use the low-res, small default avatars in the fast user switcher, like
- // we do in the menu bar.
- gfx::Image itemIcon;
- AvatarMenu::GetImageForMenuButton(item.profile_path, &itemIcon);
+ CGFloat availableWidth;
+ if (switches::IsMaterialDesignUserMenu()) {
+ int iconImageSide = 18;
+ [profileButton setDefaultImage:CreateProfileImage(item.icon, iconImageSide,
+ profiles::SHAPE_CIRCLE)];
+ availableWidth = rect.size.width - iconImageSide - imageTitleSpacing -
+ 2 * kHorizontalSpacing;
+ } else {
+ // Use the low-res, small default avatars in the fast user switcher, like
+ // we do in the menu bar.
+ gfx::Image itemIcon;
+ AvatarMenu::GetImageForMenuButton(item.profile_path, &itemIcon);
+ [profileButton setDefaultImage:CreateProfileImage(itemIcon, kSmallImageSide,
+ profiles::SHAPE_SQUARE)];
+ availableWidth = rect.size.width - kSmallImageSide - imageTitleSpacing -
+ kHorizontalSpacing;
+ }
- [profileButton setDefaultImage:CreateProfileImage(itemIcon, kSmallImageSide,
- profiles::SHAPE_SQUARE)];
[profileButton setImagePosition:NSImageLeft];
[profileButton setAlignment:NSLeftTextAlignment];
[profileButton setBordered:NO];
@@ -2110,9 +2193,6 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
NSFontAttributeName : [profileButton font]
}];
- CGFloat availableWidth = rect.size.width - kSmallImageSide -
- kImageTitleSpacing - kHorizontalSpacing;
-
if (std::ceil(textSize.width) > availableWidth)
[profileButton setToolTip:[profileButton title]];
@@ -2120,13 +2200,13 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
}
- (NSView*)createOptionsViewWithRect:(NSRect)rect
- displayLock:(BOOL)displayLock {
+ showLock:(BOOL)showLock {
NSRect viewRect = NSMakeRect(0, 0,
rect.size.width,
kBlueButtonHeight + kSmallVerticalSpacing);
base::scoped_nsobject<NSView> container([[NSView alloc] initWithFrame:rect]);
- if (displayLock) {
+ if (showLock) {
NSButton* lockButton =
[self hoverButtonWithRect:viewRect
text:l10n_util::GetNSString(
@@ -2141,7 +2221,7 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
viewRect.origin.y = NSMaxY([separator frame]);
}
- if (!switches::IsMaterialDesignUserMenu() && [self shouldShowGoIncognito]) {
+ if ([self shouldShowGoIncognito]) {
NSButton* goIncognitoButton =
[self hoverButtonWithRect:viewRect
text:l10n_util::GetNSString(
@@ -2159,9 +2239,6 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
NSString* text = isGuestSession_ ?
l10n_util::GetNSString(IDS_PROFILES_EXIT_GUEST) :
l10n_util::GetNSString(IDS_PROFILES_SWITCH_USERS_BUTTON);
- if (!isGuestSession_ && switches::IsMaterialDesignUserMenu()) {
- text = l10n_util::GetNSString(IDS_PROFILES_MANAGE_USERS_BUTTON);
- }
NSButton* switchUsersButton =
[self hoverButtonWithRect:viewRect
text:text
@@ -2216,6 +2293,86 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
return container.autorelease();
}
+- (NSView*)createMaterialDesignOptionsViewWithFrame:(NSRect)rect
+ showLock:(BOOL)showLock {
+ NSRect viewRect = NSMakeRect(0, 0, rect.size.width,
+ kBlueButtonHeight + kSmallVerticalSpacing);
+ base::scoped_nsobject<NSView> container([[NSView alloc] initWithFrame:rect]);
+ const int material_icon_size = 20;
+
+ // Create a lock profile button when supervised users exist; otherwise, create
+ // a button that closes all of the current profile's windows if more than one
+ // is open.
+ if (showLock) {
+ NSButton* lockButton =
+ [self hoverButtonWithRect:viewRect
+ text:l10n_util::GetNSString(
+ IDS_PROFILES_PROFILE_SIGNOUT_BUTTON)
+ image:NSImageFromImageSkia(gfx::CreateVectorIcon(
+ gfx::VectorIconId::LOCK,
+ material_icon_size, gfx::kChromeIconGrey))
+ action:@selector(lockProfile:)];
+ [container addSubview:lockButton];
+ viewRect.origin.y = NSMaxY([lockButton frame]);
+ } else if (!isGuestSession_) {
+ int num_browsers = 0;
+ for (auto* browser : *BrowserList::GetInstance()) {
+ Profile* current_profile = browser_->profile()->GetOriginalProfile();
+ if (browser->profile()->GetOriginalProfile() == current_profile)
+ num_browsers++;
+ }
+ if (num_browsers > 1) {
+ NSButton* closeAllWindowsButton = [self
+ hoverButtonWithRect:viewRect
+ text:l10n_util::GetNSString(
+ IDS_PROFILES_CLOSE_ALL_WINDOWS_BUTTON)
+ image:NSImageFromImageSkia(gfx::CreateVectorIcon(
+ gfx::VectorIconId::CLOSE_ALL,
+ material_icon_size, gfx::kChromeIconGrey))
+ action:@selector(closeAllWindows:)];
+ [container addSubview:closeAllWindowsButton];
+ viewRect.origin.y = NSMaxY([closeAllWindowsButton frame]);
+ }
+ }
+
+ // Create a manage users/exit guest button.
+ NSString* text =
+ isGuestSession_
+ ? l10n_util::GetNSString(IDS_PROFILES_EXIT_GUEST)
+ : l10n_util::GetNSString(IDS_PROFILES_MANAGE_USERS_BUTTON);
+ NSImage* icon = NSImageFromImageSkia(
+ gfx::CreateVectorIcon(isGuestSession_ ? gfx::VectorIconId::CLOSE_ALL
+ : gfx::VectorIconId::SETTINGS,
+ material_icon_size, gfx::kChromeIconGrey));
+ SEL action =
+ isGuestSession_ ? @selector(exitGuest:) : @selector(showUserManager:);
+ NSButton* manageUsersButton =
+ [self hoverButtonWithRect:viewRect text:text image:icon action:action];
+ viewRect.origin.y = NSMaxY([manageUsersButton frame]);
+ [container addSubview:manageUsersButton];
+
+ // Create a guest profile button.
+ if (!isGuestSession_) {
+ PrefService* service = g_browser_process->local_state();
+ DCHECK(service);
+ if (service->GetBoolean(prefs::kBrowserGuestModeEnabled)) {
+ NSButton* guestProfileButton = [self
+ hoverButtonWithRect:viewRect
+ text:l10n_util::GetNSString(
+ IDS_PROFILES_GUEST_PROFILE_NAME)
+ image:NSImageFromImageSkia(gfx::CreateVectorIcon(
+ gfx::VectorIconId::ACCOUNT_CIRCLE,
+ material_icon_size, gfx::kChromeIconGrey))
+ action:@selector(switchToGuest:)];
+ viewRect.origin.y = NSMaxY([guestProfileButton frame]);
+ [container addSubview:guestProfileButton];
+ }
+ }
+
+ [container setFrameSize:NSMakeSize(rect.size.width, viewRect.origin.y)];
+ return container.autorelease();
+}
+
- (NSView*)createAccountsListWithRect:(NSRect)rect {
base::scoped_nsobject<NSView> container([[NSView alloc] initWithFrame:rect]);
currentProfileAccounts_.clear();
@@ -2465,10 +2622,17 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
text:(NSString*)text
imageResourceId:(int)imageResourceId
action:(SEL)action {
+ ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
+ NSImage* image = rb.GetNativeImageNamed(imageResourceId).ToNSImage();
+ return [self hoverButtonWithRect:rect text:text image:image action:action];
+}
+
+- (NSButton*)hoverButtonWithRect:(NSRect)rect
+ text:(NSString*)text
+ image:(NSImage*)image
+ action:(SEL)action {
BackgroundColorHoverButton* button =
[self hoverButtonWithRect:rect text:text action:action];
- ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
- NSImage* image = rb->GetNativeImageNamed(imageResourceId).ToNSImage();
[button setDefaultImage:image];
[button setHoverImage:image];
[button setPressedImage:image];
@@ -2480,10 +2644,18 @@ class ActiveProfileObserverBridge : public AvatarMenuObserver,
- (BackgroundColorHoverButton*)hoverButtonWithRect:(NSRect)rect
text:(NSString*)text
action:(SEL)action {
+ // The vector icons in hover buttons have small embeded paddings and are
+ // therefore given an extra 2px in size to have a consistent look as the
+ // profile icons; hence the -2.0 here to left align the hover button texts
+ // with those of profile buttons.
+ const int md_image_title_spacing = kHorizontalSpacing - 2.0;
+
base::scoped_nsobject<BackgroundColorHoverButton> button(
[[BackgroundColorHoverButton alloc]
initWithFrame:rect
- imageTitleSpacing:kImageTitleSpacing
+ imageTitleSpacing:switches::IsMaterialDesignUserMenu()
+ ? md_image_title_spacing
+ : kImageTitleSpacing
backgroundColor:GetDialogBackgroundColor()]);
[button setTitle:text];
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698