| Index: ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
|
| diff --git a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
|
| index 13205e9cb8200f1fe13af1d06f0e2a9b77b70405..ba6ae8de275f17080ee428288b0bbbeba5c91462 100644
|
| --- a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
|
| +++ b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
|
| @@ -46,6 +46,7 @@
|
| #import "ios/chrome/browser/ui/popup_menu/popup_menu_view.h"
|
| #import "ios/chrome/browser/ui/reversed_animation.h"
|
| #include "ios/chrome/browser/ui/rtl_geometry.h"
|
| +#import "ios/chrome/browser/ui/toolbar/keyboard_accessory_view.h"
|
| #import "ios/chrome/browser/ui/toolbar/toolbar_controller+protected.h"
|
| #import "ios/chrome/browser/ui/toolbar/toolbar_controller.h"
|
| #import "ios/chrome/browser/ui/toolbar/toolbar_model_ios.h"
|
| @@ -115,8 +116,6 @@
|
| const CGFloat kCancelButtonTopMargin = 4.0;
|
| const CGFloat kCancelButtonLeadingMargin = 7.0;
|
| const CGFloat kCancelButtonWidth = 40.0;
|
| -const CGFloat kIpadButtonTitleFontSize = 20.0;
|
| -const CGFloat kIphoneButtonTitleFontSize = 15.0;
|
|
|
| // Additional offset to adjust the y coordinate of the determinate progress bar
|
| // up by.
|
| @@ -222,23 +221,11 @@ CGRect RectShiftedDownAndResizedForStatusBar(CGRect rect) {
|
|
|
| } // namespace
|
|
|
| -// View for the accessory view above the keyboard. Subclassed to allow playing
|
| -// input clicks when pressed.
|
| -@interface KeyboardAccessoryView : UIInputView<UIInputViewAudioFeedback>
|
| -@end
|
| -
|
| -@implementation KeyboardAccessoryView
|
| -
|
| -- (BOOL)enableInputClicksWhenVisible {
|
| - return YES;
|
| -}
|
| -
|
| -@end
|
| -
|
| // TODO(crbug.com/619982) Remove this block and add CAAnimationDelegate when we
|
| // switch the main bots to Xcode 8.
|
| #if defined(__IPHONE_10_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0)
|
| -@interface WebToolbarController ()<CAAnimationDelegate>
|
| +@interface WebToolbarController ()<CAAnimationDelegate,
|
| + KeyboardAccessoryViewDelegate>
|
| @end
|
| #endif
|
|
|
| @@ -255,8 +242,7 @@ @interface WebToolbarController ()<LocationBarDelegate,
|
| UIButton* _voiceSearchButton;
|
| OmniboxTextFieldIOS* _omniBox;
|
| UIButton* _cancelButton;
|
| - UIView* _keyBoardAccessoryView;
|
| - UIButton* _keyboardVoiceSearchButton;
|
| + KeyboardAccessoryView* _keyBoardAccessoryView;
|
| // Progress bar used to show what fraction of the page has loaded.
|
| MDCProgressView* _determinateProgressView;
|
| UIImageView* _omniboxBackground;
|
| @@ -344,7 +330,6 @@ - (void)moveVoiceOverToVoiceSearchButton;
|
| - (void)updateToolbarAlphaForFrame:(CGRect)frame;
|
| // Navigate to |query| from omnibox.
|
| - (void)loadURLForQuery:(NSString*)query;
|
| -- (UIView*)keyboardButtonWithTitle:(NSString*)title frame:(CGRect)frame;
|
| // Lazily instantiate the keyboard accessory view.
|
| - (UIView*)keyboardAccessoryView;
|
| - (void)preloadVoiceSearch:(id)sender;
|
| @@ -368,8 +353,6 @@ - (void)animationDidStop:(CAAnimation*)anim finished:(BOOL)flag;
|
| - (void)updateSnapshotWithWidth:(CGFloat)width forced:(BOOL)force;
|
| // Insert 'com' without the period if cursor is directly after a period.
|
| - (NSString*)updateTextForDotCom:(NSString*)text;
|
| -// Handle the user pressing a key in the keyboard accessory view.
|
| -- (void)pressKey:(id)sender;
|
| @end
|
|
|
| @implementation WebToolbarController
|
| @@ -892,10 +875,10 @@ - (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection {
|
| [self updateToolbarState];
|
|
|
| // Update keyboard accessory views.
|
| - BOOL hidden = [_keyboardVoiceSearchButton isHidden];
|
| + auto mode = _keyBoardAccessoryView.mode;
|
| _keyBoardAccessoryView = nil;
|
| [_omniBox setInputAccessoryView:[self keyboardAccessoryView]];
|
| - [_keyboardVoiceSearchButton setHidden:hidden];
|
| + _keyBoardAccessoryView.mode = mode;
|
| if ([_omniBox isFirstResponder]) {
|
| [_omniBox reloadInputViews];
|
| }
|
| @@ -968,8 +951,6 @@ - (IBAction)recordUserMetrics:(id)sender {
|
| base::RecordAction(UserMetricsAction("MobileToolbarStop"));
|
| } else if (sender == _voiceSearchButton) {
|
| base::RecordAction(UserMetricsAction("MobileToolbarVoiceSearch"));
|
| - } else if (sender == _keyboardVoiceSearchButton) {
|
| - base::RecordAction(UserMetricsAction("MobileCustomRowVoiceSearch"));
|
| } else if (sender == _starButton) {
|
| base::RecordAction(UserMetricsAction("MobileToolbarToggleBookmark"));
|
| } else {
|
| @@ -1280,7 +1261,7 @@ - (void)locationBarHasBecomeFirstResponder {
|
| [self.delegate locationBarDidBecomeFirstResponder:self];
|
| [self animateMaterialOmnibox];
|
|
|
| - [_keyboardVoiceSearchButton setHidden:NO];
|
| + _keyBoardAccessoryView.mode = VOICE_SEARCH;
|
|
|
| // Record the appropriate user action for focusing the omnibox.
|
| web::WebState* webState = [self.delegate currentWebState];
|
| @@ -1318,10 +1299,14 @@ - (void)locationBarChanged {
|
| // If the voice search button is visible but about to be hidden (i.e.
|
| // the omnibox is no longer empty) then this is the first omnibox text so
|
| // record a user action.
|
| - if (![_keyboardVoiceSearchButton isHidden] && editingAndNotEmpty) {
|
| + if (_keyBoardAccessoryView.mode == VOICE_SEARCH && editingAndNotEmpty) {
|
| base::RecordAction(UserMetricsAction("MobileFirstTextInOmnibox"));
|
| }
|
| - [_keyboardVoiceSearchButton setHidden:editingAndNotEmpty];
|
| + if (editingAndNotEmpty) {
|
| + _keyBoardAccessoryView.mode = KEY_SHORTCUTS;
|
| + } else {
|
| + _keyBoardAccessoryView.mode = VOICE_SEARCH;
|
| + }
|
| }
|
|
|
| - (web::WebState*)getWebState {
|
| @@ -1473,6 +1458,35 @@ - (void)receiveQRScannerResult:(NSString*)result loadImmediately:(BOOL)load {
|
| }
|
|
|
| #pragma mark -
|
| +#pragma mark KeyboardAccessoryViewDelegate
|
| +
|
| +- (void)keyboardAccessoryVoiceSearchTouchDown {
|
| + if (ios::GetChromeBrowserProvider()
|
| + ->GetVoiceSearchProvider()
|
| + ->IsVoiceSearchEnabled()) {
|
| + [self preloadVoiceSearch:_keyBoardAccessoryView];
|
| + }
|
| +}
|
| +
|
| +- (void)keyboardAccessoryVoiceSearchTouchUpInside {
|
| + if (ios::GetChromeBrowserProvider()
|
| + ->GetVoiceSearchProvider()
|
| + ->IsVoiceSearchEnabled()) {
|
| + base::RecordAction(UserMetricsAction("MobileCustomRowVoiceSearch"));
|
| + GenericChromeCommand* command =
|
| + [[GenericChromeCommand alloc] initWithTag:IDC_VOICE_SEARCH];
|
| + [_keyBoardAccessoryView chromeExecuteCommand:command];
|
| + } else {
|
| + _keyBoardAccessoryView.mode = KEY_SHORTCUTS;
|
| + }
|
| +}
|
| +
|
| +- (void)keyPressed:(NSString*)title {
|
| + NSString* text = [self updateTextForDotCom:title];
|
| + [_omniBox insertTextWhileEditing:text];
|
| +}
|
| +
|
| +#pragma mark -
|
| #pragma mark Private methods.
|
|
|
| - (UIButton*)cancelButton {
|
| @@ -1827,136 +1841,18 @@ - (void)loadURLForQuery:(NSString*)query {
|
| }
|
| }
|
|
|
| -- (UIView*)keyboardButtonWithTitle:(NSString*)title frame:(CGRect)frame {
|
| - UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
|
| - UIFont* font = nil;
|
| - UIImage* backgroundImage = nil;
|
| - if (IsIPadIdiom()) {
|
| - font = GetUIFont(FONT_HELVETICA, false, kIpadButtonTitleFontSize);
|
| - } else {
|
| - font = GetUIFont(FONT_HELVETICA, true, kIphoneButtonTitleFontSize);
|
| - }
|
| - // TODO(leng): Consider moving these images to pak files as well.
|
| - backgroundImage = [UIImage imageNamed:@"keyboard_button"];
|
| -
|
| - button.frame = frame;
|
| - [button setTitle:title forState:UIControlStateNormal];
|
| - [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
|
| - [button.titleLabel setFont:font];
|
| - [button setBackgroundImage:backgroundImage forState:UIControlStateNormal];
|
| - [button addTarget:self
|
| - action:@selector(pressKey:)
|
| - forControlEvents:UIControlEventTouchUpInside];
|
| - button.isAccessibilityElement = YES;
|
| - [button setAccessibilityLabel:title];
|
| -
|
| - return button;
|
| -}
|
| -
|
| - (UIView*)keyboardAccessoryView {
|
| - const CGFloat kViewHeightTablet = 70.0;
|
| - const CGFloat kViewHeightPhone = 43.0;
|
| - const CGFloat kButtonInset = 5.0;
|
| - const CGFloat kButtonSizeXTablet = 61.0;
|
| - const CGFloat kButtonSizeXPhone = 46.0;
|
| - const CGFloat kButtonSizeYTablet = 62.0;
|
| - const CGFloat kButtonSizeYPhone = 35.0;
|
| - const CGFloat kBetweenButtonSpacing = 15.0;
|
| - const CGFloat kBetweenButtonSpacingPhone = 7.0;
|
| -
|
| - if (_keyBoardAccessoryView)
|
| - return _keyBoardAccessoryView;
|
| -
|
| - const BOOL isTablet = IsIPadIdiom() && !IsCompactTablet(self.view);
|
| -
|
| - // TODO(pinkerton): purge this view when low memory.
|
| - CGFloat width = [[UIScreen mainScreen] bounds].size.width;
|
| - CGFloat height = isTablet ? kViewHeightTablet : kViewHeightPhone;
|
| - CGRect frame = CGRectMake(0.0, 0.0, width, height);
|
| -
|
| - _keyBoardAccessoryView =
|
| - [[KeyboardAccessoryView alloc] initWithFrame:frame
|
| - inputViewStyle:UIInputViewStyleKeyboard];
|
| - [_keyBoardAccessoryView setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
|
| -
|
| - NSArray* buttonTitles =
|
| - [NSArray arrayWithObjects:@":", @".", @"-", @"/", kDotComTLD, nil];
|
| -
|
| - // Center buttons in available space by placing them within a parent view
|
| - // that auto-centers.
|
| - CGFloat betweenButtonSpacing =
|
| - isTablet ? kBetweenButtonSpacing : kBetweenButtonSpacingPhone;
|
| - const CGFloat buttonWidth = isTablet ? kButtonSizeXTablet : kButtonSizeXPhone;
|
| -
|
| - CGFloat totalWidth = (buttonTitles.count * buttonWidth) +
|
| - ((buttonTitles.count - 1) * betweenButtonSpacing);
|
| - CGFloat indent = floor((width - totalWidth) / 2.0);
|
| - if (indent < kButtonInset)
|
| - indent = kButtonInset;
|
| - CGRect parentViewRect = CGRectMake(indent, 0.0, totalWidth, height);
|
| - UIView* parentView = [[UIView alloc] initWithFrame:parentViewRect];
|
| - [parentView setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin |
|
| - UIViewAutoresizingFlexibleRightMargin];
|
| - [_keyBoardAccessoryView addSubview:parentView];
|
| -
|
| - // Create the buttons, starting at the left edge of |parentView|.
|
| - CGRect currentFrame =
|
| - CGRectMake(0.0, kButtonInset, buttonWidth,
|
| - isTablet ? kButtonSizeYTablet : kButtonSizeYPhone);
|
| -
|
| - for (NSString* title in buttonTitles) {
|
| - UIView* button = [self keyboardButtonWithTitle:title frame:currentFrame];
|
| - [parentView addSubview:button];
|
| - currentFrame.origin.x = CGRectGetMaxX(currentFrame) + betweenButtonSpacing;
|
| - }
|
| -
|
| - // Create the voice search button and add it to _keyBoardAccessoryView over
|
| - // the text buttons.
|
| - _keyboardVoiceSearchButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
| - [_keyboardVoiceSearchButton
|
| - setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
|
| - [_keyboardVoiceSearchButton setTag:IDC_VOICE_SEARCH];
|
| - SetA11yLabelAndUiAutomationName(_keyboardVoiceSearchButton,
|
| - IDS_IOS_ACCNAME_VOICE_SEARCH,
|
| - @"Voice Search");
|
| - // TODO(leng): Consider moving these icons into a pak file.
|
| - UIImage* voiceRow = [UIImage imageNamed:@"custom_row_voice"];
|
| - UIImage* voiceRowPressed = [UIImage imageNamed:@"custom_row_voice_pressed"];
|
| - [_keyboardVoiceSearchButton setBackgroundImage:voiceRow
|
| - forState:UIControlStateNormal];
|
| - [_keyboardVoiceSearchButton setBackgroundImage:voiceRowPressed
|
| - forState:UIControlStateHighlighted];
|
| -
|
| - UIImage* voiceIcon = [UIImage imageNamed:@"voice_icon_keyboard_accessory"];
|
| - [_keyboardVoiceSearchButton setAdjustsImageWhenHighlighted:NO];
|
| - [_keyboardVoiceSearchButton setImage:voiceIcon forState:UIControlStateNormal];
|
| - [_keyboardVoiceSearchButton setFrame:[_keyBoardAccessoryView bounds]];
|
| -
|
| - // Only add the voice search actions if voice search is enabled.
|
| - if (ios::GetChromeBrowserProvider()
|
| - ->GetVoiceSearchProvider()
|
| - ->IsVoiceSearchEnabled()) {
|
| - [_keyboardVoiceSearchButton addTarget:self
|
| - action:@selector(recordUserMetrics:)
|
| - forControlEvents:UIControlEventTouchUpInside];
|
| - [_keyboardVoiceSearchButton addTarget:_keyboardVoiceSearchButton
|
| - action:@selector(chromeExecuteCommand:)
|
| - forControlEvents:UIControlEventTouchUpInside];
|
| - [_keyboardVoiceSearchButton addTarget:self
|
| - action:@selector(preloadVoiceSearch:)
|
| - forControlEvents:UIControlEventTouchDown];
|
| - } else {
|
| - [_keyboardVoiceSearchButton addTarget:self
|
| - action:@selector(ignoreVoiceSearch:)
|
| - forControlEvents:UIControlEventTouchUpInside];
|
| + if (!_keyBoardAccessoryView) {
|
| + NSArray<NSString*>* buttonTitles =
|
| + [NSArray arrayWithObjects:@":", @".", @"-", @"/", kDotComTLD, nil];
|
| + _keyBoardAccessoryView =
|
| + [[KeyboardAccessoryView alloc] initWithButtons:buttonTitles
|
| + delegate:self];
|
| + [_keyBoardAccessoryView
|
| + setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
|
| + _hardwareKeyboardWatcher = [[HardwareKeyboardWatcher alloc]
|
| + initWithAccessoryView:_keyBoardAccessoryView];
|
| }
|
| -
|
| - [_keyBoardAccessoryView addSubview:_keyboardVoiceSearchButton];
|
| -
|
| - // Reset the external keyboard watcher.
|
| - _hardwareKeyboardWatcher = [[HardwareKeyboardWatcher alloc]
|
| - initWithAccessoryView:_keyBoardAccessoryView];
|
| -
|
| return _keyBoardAccessoryView;
|
| }
|
|
|
| @@ -1964,10 +1860,6 @@ - (void)preloadVoiceSearch:(id)sender {
|
| DCHECK(ios::GetChromeBrowserProvider()
|
| ->GetVoiceSearchProvider()
|
| ->IsVoiceSearchEnabled());
|
| - [sender removeTarget:self
|
| - action:@selector(preloadVoiceSearch:)
|
| - forControlEvents:UIControlEventTouchDown];
|
| -
|
| // Use a GenericChromeCommand because |sender| already has a tag set for a
|
| // different command.
|
| GenericChromeCommand* command =
|
| @@ -1975,12 +1867,6 @@ - (void)preloadVoiceSearch:(id)sender {
|
| [sender chromeExecuteCommand:command];
|
| }
|
|
|
| -// Called when the keyboard voice search button is tapped with voice search
|
| -// disabled. Hides the voice search button but takes no other action.
|
| -- (void)ignoreVoiceSearch:(id)sender {
|
| - [_keyboardVoiceSearchButton setHidden:YES];
|
| -}
|
| -
|
| - (CGFloat)omniboxLeading {
|
| // Compute what the leading (x-origin) position for the omniboox should be
|
| // based on what other controls are active.
|
| @@ -2530,13 +2416,6 @@ - (NSString*)updateTextForDotCom:(NSString*)text {
|
| return text;
|
| }
|
|
|
| -- (void)pressKey:(id)sender {
|
| - DCHECK([sender isKindOfClass:[UIButton class]]);
|
| - [[UIDevice currentDevice] playInputClick];
|
| - NSString* text = [self updateTextForDotCom:[sender currentTitle]];
|
| - [_omniBox insertTextWhileEditing:text];
|
| -}
|
| -
|
| @end
|
|
|
| @implementation WebToolbarController (Testing)
|
|
|