Commit 4d93949d authored by kevers@chromium.org's avatar kevers@chromium.org

Update insets on change to window bounds.

In overscroll mode, any window with web contents that overlaps the virtual keyboard has insets in order to facilitate scrolling to the bottom of the document.  These insets are updated whenever the keyboard is shown or hidden.  This patch adds another update in the event that a window moves while the keyboard is visible.  This case can occur after a screen rotation while the keyboard is shown.


BUG=391337

Review URL: https://codereview.chromium.org/368323002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@283873 0039d316-1c4b-4281-b951-d872f2087c98
parent 94cd5410
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/render_widget_host_view.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/aura/window_delegate.h" #include "ui/aura/window_delegate.h"
#include "ui/aura/window_observer.h"
#include "ui/base/cursor/cursor.h" #include "ui/base/cursor/cursor.h"
#include "ui/base/hit_test.h" #include "ui/base/hit_test.h"
#include "ui/base/ime/input_method.h" #include "ui/base/ime/input_method.h"
...@@ -141,6 +142,17 @@ void ToggleTouchEventLogging(bool enable) { ...@@ -141,6 +142,17 @@ void ToggleTouchEventLogging(bool enable) {
#endif #endif
} }
aura::Window *GetFrameWindow(aura::Window *window) {
// Each container window has a non-negative id. Stop traversing at the child
// of a container window.
if (!window)
return NULL;
while(window->parent() && window->parent()->id() < 0) {
window = window->parent();
}
return window;
}
} // namespace } // namespace
namespace keyboard { namespace keyboard {
...@@ -189,6 +201,20 @@ void CallbackAnimationObserver::OnLayerAnimationAborted( ...@@ -189,6 +201,20 @@ void CallbackAnimationObserver::OnLayerAnimationAborted(
animator_->RemoveObserver(this); animator_->RemoveObserver(this);
} }
class WindowBoundsChangeObserver : public aura::WindowObserver {
public:
virtual void OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) OVERRIDE;
};
void WindowBoundsChangeObserver::OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds, const gfx::Rect& new_bounds) {
KeyboardController* controller = KeyboardController::GetInstance();
if (controller)
controller->UpdateWindowInsets(window);
}
// static // static
KeyboardController* KeyboardController::instance_ = NULL; KeyboardController* KeyboardController::instance_ = NULL;
...@@ -202,6 +228,7 @@ KeyboardController::KeyboardController(KeyboardControllerProxy* proxy) ...@@ -202,6 +228,7 @@ KeyboardController::KeyboardController(KeyboardControllerProxy* proxy)
CHECK(proxy); CHECK(proxy);
input_method_ = proxy_->GetInputMethod(); input_method_ = proxy_->GetInputMethod();
input_method_->AddObserver(this); input_method_->AddObserver(this);
window_bounds_observer_.reset(new WindowBoundsChangeObserver());
} }
KeyboardController::~KeyboardController() { KeyboardController::~KeyboardController() {
...@@ -270,9 +297,8 @@ void KeyboardController::NotifyKeyboardBoundsChanging( ...@@ -270,9 +297,8 @@ void KeyboardController::NotifyKeyboardBoundsChanging(
if (overlap > 0 && overlap < window_bounds.height()) if (overlap > 0 && overlap < window_bounds.height())
view->SetInsets(gfx::Insets(0, 0, overlap, 0)); view->SetInsets(gfx::Insets(0, 0, overlap, 0));
else else
view->SetInsets(gfx::Insets(0, 0, 0, 0)); view->SetInsets(gfx::Insets());
// TODO(kevers): Add window observer to native window to update AddBoundsChangedObserver(window);
// insets on a window move or resize.
} }
} }
} }
...@@ -384,6 +410,33 @@ void KeyboardController::OnShowImeIfNeeded() { ...@@ -384,6 +410,33 @@ void KeyboardController::OnShowImeIfNeeded() {
ShowKeyboardInternal(); ShowKeyboardInternal();
} }
void KeyboardController::UpdateWindowInsets(aura::Window* window) {
aura::Window *keyboard_window = proxy_->GetKeyboardWindow();
if (window == keyboard_window)
return;
bool enableInsets = (keyboard_window->GetRootWindow() ==
window->GetRootWindow()) && keyboard::IsKeyboardOverscrollEnabled() &&
proxy_->GetKeyboardWindow()->IsVisible();
scoped_ptr<content::RenderWidgetHostIterator> widgets(
content::RenderWidgetHost::GetRenderWidgetHosts());
while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
content::RenderWidgetHostView* view = widget->GetView();
if (view && window->Contains(view->GetNativeView())) {
gfx::Rect window_bounds = view->GetNativeView()->GetBoundsInScreen();
gfx::Rect intersect = gfx::IntersectRects(window_bounds,
proxy_->GetKeyboardWindow()->bounds());
int overlap = enableInsets ? intersect.height() : 0;
if (overlap > 0 && overlap < window_bounds.height())
view->SetInsets(gfx::Insets(0, 0, overlap, 0));
else
view->SetInsets(gfx::Insets());
return;
}
}
}
void KeyboardController::ShowKeyboardInternal() { void KeyboardController::ShowKeyboardInternal() {
if (!container_.get()) if (!container_.get())
return; return;
...@@ -460,8 +513,11 @@ void KeyboardController::ResetWindowInsets() { ...@@ -460,8 +513,11 @@ void KeyboardController::ResetWindowInsets() {
content::RenderWidgetHost::GetRenderWidgetHosts()); content::RenderWidgetHost::GetRenderWidgetHosts());
while (content::RenderWidgetHost* widget = widgets->GetNextHost()) { while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
content::RenderWidgetHostView* view = widget->GetView(); content::RenderWidgetHostView* view = widget->GetView();
if (view) if (view) {
view->SetInsets(insets); view->SetInsets(insets);
aura::Window *window = view->GetNativeView();
RemoveBoundsChangedObserver(window);
}
} }
} }
...@@ -480,4 +536,20 @@ void KeyboardController::HideAnimationFinished() { ...@@ -480,4 +536,20 @@ void KeyboardController::HideAnimationFinished() {
proxy_->HideKeyboardContainer(container_.get()); proxy_->HideKeyboardContainer(container_.get());
} }
void KeyboardController::AddBoundsChangedObserver(aura::Window* window) {
aura::Window* target_window = GetFrameWindow(window);
if (target_window &&
!target_window->HasObserver(window_bounds_observer_.get())) {
target_window->AddObserver(window_bounds_observer_.get());
}
}
void KeyboardController::RemoveBoundsChangedObserver(aura::Window* window) {
aura::Window* target_window = GetFrameWindow(window);
if (target_window &&
target_window->HasObserver(window_bounds_observer_.get())) {
target_window->RemoveObserver(window_bounds_observer_.get());
}
}
} // namespace keyboard } // namespace keyboard
...@@ -27,6 +27,7 @@ class TextInputClient; ...@@ -27,6 +27,7 @@ class TextInputClient;
namespace keyboard { namespace keyboard {
class CallbackAnimationObserver; class CallbackAnimationObserver;
class WindowBoundsChangeObserver;
class KeyboardControllerObserver; class KeyboardControllerObserver;
class KeyboardControllerProxy; class KeyboardControllerProxy;
...@@ -98,6 +99,9 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver, ...@@ -98,6 +99,9 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
return current_keyboard_bounds_; return current_keyboard_bounds_;
} }
// Updates insets on web content window
void UpdateWindowInsets(aura::Window* window);
private: private:
// For access to Observer methods for simulation. // For access to Observer methods for simulation.
friend class KeyboardControllerTest; friend class KeyboardControllerTest;
...@@ -133,12 +137,20 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver, ...@@ -133,12 +137,20 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
void ShowAnimationFinished(); void ShowAnimationFinished();
void HideAnimationFinished(); void HideAnimationFinished();
// Adds or removes an observer for tracking changes to a window size or
// position while the keyboard is displayed. Any window repositioning
// invalidates insets for overscrolling.
void AddBoundsChangedObserver(aura::Window* window);
void RemoveBoundsChangedObserver(aura::Window* window);
scoped_ptr<KeyboardControllerProxy> proxy_; scoped_ptr<KeyboardControllerProxy> proxy_;
scoped_ptr<aura::Window> container_; scoped_ptr<aura::Window> container_;
// CallbackAnimationObserver should destructed before container_ because it // CallbackAnimationObserver should destructed before container_ because it
// uses container_'s animator. // uses container_'s animator.
scoped_ptr<CallbackAnimationObserver> animation_observer_; scoped_ptr<CallbackAnimationObserver> animation_observer_;
scoped_ptr<WindowBoundsChangeObserver> window_bounds_observer_;
ui::InputMethod* input_method_; ui::InputMethod* input_method_;
bool keyboard_visible_; bool keyboard_visible_;
bool lock_keyboard_; bool lock_keyboard_;
......
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