Commit 0ad8bf2f authored by Yuwei Huang's avatar Yuwei Huang Committed by Commit Bot

[CRD iOS] Rework the HostView keyboard layout

When rotating the screen on iPad with the keyboard showing, for some
reason the host view will become improperly laid out. Part of the view
gets overlaid by the keyboard.

My suspicion is the view frame becomes inconsistent when the rotation
happens.

This CL fixes the problem by reworking the keyboard layout using
constraints. It also makes GLRenderer cache the view size before the
canvas is created.

Bug: 751273
Change-Id: I5146ff6bf602eef1857259e5e50ca6be1d952a68
Reviewed-on: https://chromium-review.googlesource.com/596913
Commit-Queue: Yuwei Huang <yuweih@chromium.org>
Reviewed-by: default avatarScott Nichols <nicholss@chromium.org>
Cr-Commit-Position: refs/heads/master@{#491519}
parent 8af2ef71
......@@ -106,6 +106,9 @@ void GlRenderer::OnCursorShapeChanged(const protocol::CursorShapeInfo& shape) {
void GlRenderer::OnSurfaceCreated(std::unique_ptr<Canvas> canvas) {
DCHECK(thread_checker_.CalledOnValidThread());
canvas_ = std::move(canvas);
if (view_width_ > 0 && view_height_ > 0) {
canvas_->SetViewSize(view_width_, view_height_);
}
for (auto& drawable : drawables_) {
drawable->SetCanvas(canvas_->GetWeakPtr());
}
......@@ -113,10 +116,13 @@ void GlRenderer::OnSurfaceCreated(std::unique_ptr<Canvas> canvas) {
void GlRenderer::OnSurfaceChanged(int view_width, int view_height) {
DCHECK(thread_checker_.CalledOnValidThread());
view_width_ = view_width;
view_height_ = view_height;
if (!canvas_) {
LOG(WARNING) << "Trying to set the view size when the canvas is not ready.";
return;
}
canvas_->SetViewSize(view_width, view_height);
RequestRender();
}
......
......@@ -127,6 +127,10 @@ class GlRenderer {
int canvas_width_ = 0;
int canvas_height_ = 0;
// Used to store the view size before the canvas is created.
int view_width_ = 0;
int view_height_ = 0;
std::unique_ptr<Canvas> canvas_;
GlCursor cursor_;
......
......@@ -51,6 +51,8 @@ static const CGFloat kMoveFABAnimationTime = 0.3;
// When set to true, ClientKeyboard will immediately resign first responder
// after it becomes first responder.
BOOL _blocksKeyboard;
NSLayoutConstraint* _keyboardHeightConstraint;
EAGLView* _hostView;
}
@end
......@@ -79,15 +81,21 @@ static const CGFloat kMoveFABAnimationTime = 0.3;
#pragma mark - UIViewController
- (void)loadView {
EAGLView* glView = [[EAGLView alloc] initWithFrame:CGRectZero];
glView.displayTaskRunner =
remoting::ChromotingClientRuntime::GetInstance()->display_task_runner();
self.view = glView;
}
- (void)viewDidLoad {
[super viewDidLoad];
_hostView = [[EAGLView alloc] initWithFrame:CGRectZero];
_hostView.displayTaskRunner =
remoting::ChromotingClientRuntime::GetInstance()->display_task_runner();
_hostView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:_hostView];
[NSLayoutConstraint activateConstraints:@[
[_hostView.topAnchor constraintEqualToAnchor:self.view.topAnchor],
[_hostView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[_hostView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
]];
[self setKeyboardSize:CGSizeZero needsLayout:NO];
_floatingButton =
[MDCFloatingButton floatingButtonWithShape:MDCFloatingButtonShapeMini];
// Note(nicholss): Setting title to " " because the FAB requires the title
......@@ -107,13 +115,13 @@ static const CGFloat kMoveFABAnimationTime = 0.3;
primaryImage:RemotingTheme.menuIcon
activeImage:RemotingTheme.closeIcon];
[_floatingButton addSubview:_actionImageView];
[self.view addSubview:_floatingButton];
[_hostView addSubview:_floatingButton];
[self applyInputMode];
_clientKeyboard = [[ClientKeyboard alloc] init];
_clientKeyboard.delegate = self;
[self.view addSubview:_clientKeyboard];
[_hostView addSubview:_clientKeyboard];
NSDictionary* views = @{@"fab" : _floatingButton};
NSDictionary* metrics = @{ @"inset" : @(kFabInset) };
......@@ -142,7 +150,7 @@ static const CGFloat kMoveFABAnimationTime = 0.3;
[super viewDidUnload];
// TODO(nicholss): There needs to be a hook to tell the client we are done.
[(EAGLView*)self.view stop];
[_hostView stop];
_clientGestures = nil;
_client = nil;
}
......@@ -154,16 +162,11 @@ static const CGFloat kMoveFABAnimationTime = 0.3;
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (!_surfaceCreated) {
[_client.displayHandler onSurfaceCreated:(EAGLView*)self.view];
[_client.displayHandler onSurfaceCreated:_hostView];
_surfaceCreated = YES;
}
// viewDidLayoutSubviews may be called before viewDidAppear, in which case
// the surface is not ready to handle the transformation matrix.
// Call onSurfaceChanged here to cover that case.
[_client surfaceChanged:self.view.frame];
[self resizeHostToFitIfNeeded];
[PhysicalKeyboardDetector detectOnView:self.view
[PhysicalKeyboardDetector detectOnView:_hostView
callback:^(BOOL hasPhysicalKeyboard) {
if (hasPhysicalKeyboard) {
_clientKeyboard.hasPhysicalKeyboard =
......@@ -182,7 +185,7 @@ static const CGFloat kMoveFABAnimationTime = 0.3;
if (!_clientGestures) {
_clientGestures =
[[ClientGestures alloc] initWithView:self.view client:_client];
[[ClientGestures alloc] initWithView:_hostView client:_client];
_clientGestures.delegate = self;
}
[[NSNotificationCenter defaultCenter]
......@@ -210,12 +213,8 @@ static const CGFloat kMoveFABAnimationTime = 0.3;
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
if (self.view.window != nil) {
// If the context is not set yet, the view size will be set in
// viewDidAppear.
[_client surfaceChanged:self.view.bounds];
[self resizeHostToFitIfNeeded];
}
[_client surfaceChanged:_hostView.bounds];
[self resizeHostToFitIfNeeded];
[self updateFABConstraintsAnimated:NO];
}
......@@ -250,26 +249,11 @@ static const CGFloat kMoveFABAnimationTime = 0.3;
[[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey]
CGRectValue]
.size;
if (_keyboardSize.height != keyboardSize.height) {
CGFloat deltaHeight = keyboardSize.height - _keyboardSize.height;
[UIView animateWithDuration:kKeyboardAnimationTime
animations:^{
CGRect f = self.view.frame;
f.size.height -= deltaHeight;
self.view.frame = f;
}];
_keyboardSize = keyboardSize;
}
[self setKeyboardSize:keyboardSize needsLayout:YES];
}
- (void)keyboardWillHide:(NSNotification*)notification {
[UIView animateWithDuration:kKeyboardAnimationTime
animations:^{
CGRect f = self.view.frame;
f.size.height += _keyboardSize.height;
self.view.frame = f;
}];
_keyboardSize = CGSizeZero;
[self setKeyboardSize:CGSizeZero needsLayout:YES];
}
#pragma mark - ClientKeyboardDelegate
......@@ -364,8 +348,8 @@ static const CGFloat kMoveFABAnimationTime = 0.3;
if (_settings.shouldResizeHostToFit && !isPhonePortrait &&
![self isKeyboardActive]) {
[_client setHostResolution:self.view.frame.size
scale:self.view.contentScaleFactor];
[_client setHostResolution:_hostView.frame.size
scale:_hostView.contentScaleFactor];
}
}
......@@ -467,17 +451,12 @@ static const CGFloat kMoveFABAnimationTime = 0.3;
restoresKeyboard:NO
handler:settingsHandler];
void (^moveFABHandler)(UIAlertAction*) = ^(UIAlertAction*) {
[weakSelf moveFAB];
[_actionImageView setActive:NO animated:YES];
};
[alert addAction:[UIAlertAction
actionWithTitle:l10n_util::GetNSString(
(_fabIsRight)
? IDS_MOVE_FAB_LEFT_BUTTON
: IDS_MOVE_FAB_RIGHT_BUTTON)
style:UIAlertActionStyleDefault
handler:moveFABHandler]];
[self addActionToAlert:alert
title:(_fabIsRight) ? IDS_MOVE_FAB_LEFT_BUTTON
: IDS_MOVE_FAB_RIGHT_BUTTON
handler:^() {
[weakSelf moveFAB];
}];
__weak UIAlertController* weakAlert = alert;
void (^cancelHandler)() = ^() {
......@@ -489,7 +468,7 @@ static const CGFloat kMoveFABAnimationTime = 0.3;
restoresKeyboard:YES
handler:cancelHandler];
alert.popoverPresentationController.sourceView = self.view;
alert.popoverPresentationController.sourceView = _hostView;
// Target the alert menu at the top middle of the FAB.
alert.popoverPresentationController.sourceRect = CGRectMake(
_floatingButton.center.x, _floatingButton.frame.origin.y, 1.0, 1.0);
......@@ -541,4 +520,22 @@ static const CGFloat kMoveFABAnimationTime = 0.3;
handler:handler];
}
- (void)setKeyboardSize:(CGSize)keyboardSize needsLayout:(BOOL)needsLayout {
_keyboardSize = keyboardSize;
if (_keyboardHeightConstraint) {
_keyboardHeightConstraint.active = NO;
}
_keyboardHeightConstraint =
[_hostView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor
constant:-keyboardSize.height];
_keyboardHeightConstraint.active = YES;
if (needsLayout) {
[UIView animateWithDuration:kKeyboardAnimationTime
animations:^{
[self.view setNeedsLayout];
}];
}
}
@end
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