Commit aacb7cf3 authored by Blake O'Hare's avatar Blake O'Hare Committed by Commit Bot

Moving floating keyboard to edge will move it to adjacent display.

This isn't an ideal UX, although there is currently no defined UX
for this and this mostly just lays the foundation of any future
implementation. When the actual touch point (where the user's finger
is) approaches within 10 pixels of the display edge where there is
another display attached, the keyboard will transfer to the new display
in a default location.

This uses a similar mechanism as the ContainerBehavior change, where
the new display is queued on the KeyboardController and the keyboard
is then hidden. The HideAnimationFinished handler will then check for
any queued display changes, and re-open the keyboard on the new
display.

Bug: 828701
Change-Id: I7d513791b5bd2de9133f6014469cd03c3fa44899
Reviewed-on: https://chromium-review.googlesource.com/1009507
Commit-Queue: Blake O'Hare <blakeo@chromium.org>
Reviewed-by: default avatarYuichiro Hanada <yhanada@chromium.org>
Cr-Commit-Position: refs/heads/master@{#550126}
parent 7999fe5f
...@@ -41,6 +41,8 @@ jumbo_component("keyboard") { ...@@ -41,6 +41,8 @@ jumbo_component("keyboard") {
"notification_manager.h", "notification_manager.h",
"queued_container_type.cc", "queued_container_type.cc",
"queued_container_type.h", "queued_container_type.h",
"queued_display_change.cc",
"queued_display_change.h",
] ]
defines = [ "KEYBOARD_IMPLEMENTATION" ] defines = [ "KEYBOARD_IMPLEMENTATION" ]
......
...@@ -65,7 +65,7 @@ class KEYBOARD_EXPORT ContainerBehavior { ...@@ -65,7 +65,7 @@ class KEYBOARD_EXPORT ContainerBehavior {
const gfx::Size& screen_size) = 0; const gfx::Size& screen_size) = 0;
virtual void HandlePointerEvent(const ui::LocatedEvent& event, virtual void HandlePointerEvent(const ui::LocatedEvent& event,
const gfx::Rect& display_bounds) = 0; const display::Display& current_display) = 0;
virtual ContainerType GetType() const = 0; virtual ContainerType GetType() const = 0;
......
...@@ -182,7 +182,7 @@ bool ContainerFloatingBehavior::IsDragHandle( ...@@ -182,7 +182,7 @@ bool ContainerFloatingBehavior::IsDragHandle(
void ContainerFloatingBehavior::HandlePointerEvent( void ContainerFloatingBehavior::HandlePointerEvent(
const ui::LocatedEvent& event, const ui::LocatedEvent& event,
const gfx::Rect& display_bounds) { const display::Display& current_display) {
// Cannot call UI-backed operations without a KeyboardController // Cannot call UI-backed operations without a KeyboardController
DCHECK(controller_); DCHECK(controller_);
auto kb_offset = gfx::Vector2d(event.x(), event.y()); auto kb_offset = gfx::Vector2d(event.x(), event.y());
...@@ -245,10 +245,28 @@ void ContainerFloatingBehavior::HandlePointerEvent( ...@@ -245,10 +245,28 @@ void ContainerFloatingBehavior::HandlePointerEvent(
const gfx::Point new_keyboard_location = const gfx::Point new_keyboard_location =
drag_descriptor_->original_keyboard_location() + drag_descriptor_->original_keyboard_location() +
cumulative_drag_offset; cumulative_drag_offset;
const gfx::Rect new_bounds = gfx::Rect new_bounds =
gfx::Rect(new_keyboard_location, keyboard_bounds.size()); gfx::Rect(new_keyboard_location, keyboard_bounds.size());
controller_->MoveKeyboard(new_bounds);
SavePosition(container->bounds(), display_bounds.size()); DisplayUtil display_util;
const display::Display& new_display =
display_util.FindAdjacentDisplayIfPointIsNearMargin(
current_display, current_drag_location);
if (current_display.id() == new_display.id()) {
controller_->MoveKeyboard(new_bounds);
} else {
new_bounds =
ContainKeyboardToScreenBounds(new_bounds, new_display.bounds());
// Since the keyboard has jumped across screens, cancel the current
// drag descriptor as though the user has lifted their finger.
drag_descriptor_ = nullptr;
// Enqueue a transition to the adjacent display.
// TODO(blakeo): pass new_bounds to display transition.
controller_->MoveToDisplayWithTransition(new_display);
}
SavePosition(container->bounds(), new_display.size());
} }
break; break;
......
...@@ -50,7 +50,7 @@ class KEYBOARD_EXPORT ContainerFloatingBehavior : public ContainerBehavior { ...@@ -50,7 +50,7 @@ class KEYBOARD_EXPORT ContainerFloatingBehavior : public ContainerBehavior {
void SavePosition(const gfx::Rect& keyboard_bounds, void SavePosition(const gfx::Rect& keyboard_bounds,
const gfx::Size& screen_size) override; const gfx::Size& screen_size) override;
void HandlePointerEvent(const ui::LocatedEvent& event, void HandlePointerEvent(const ui::LocatedEvent& event,
const gfx::Rect& display_bounds) override; const display::Display& current_display) override;
void SetCanonicalBounds(aura::Window* container, void SetCanonicalBounds(aura::Window* container,
const gfx::Rect& display_bounds) override; const gfx::Rect& display_bounds) override;
ContainerType GetType() const override; ContainerType GetType() const override;
......
...@@ -95,7 +95,7 @@ bool ContainerFullWidthBehavior::IsDragHandle( ...@@ -95,7 +95,7 @@ bool ContainerFullWidthBehavior::IsDragHandle(
void ContainerFullWidthBehavior::HandlePointerEvent( void ContainerFullWidthBehavior::HandlePointerEvent(
const ui::LocatedEvent& event, const ui::LocatedEvent& event,
const gfx::Rect& display_bounds) { const display::Display& current_display) {
// No-op. Nothing special to do for pointer events. // No-op. Nothing special to do for pointer events.
} }
......
...@@ -42,7 +42,7 @@ class KEYBOARD_EXPORT ContainerFullWidthBehavior : public ContainerBehavior { ...@@ -42,7 +42,7 @@ class KEYBOARD_EXPORT ContainerFullWidthBehavior : public ContainerBehavior {
void SavePosition(const gfx::Rect& keyboard_bounds, void SavePosition(const gfx::Rect& keyboard_bounds,
const gfx::Size& screen_size) override; const gfx::Size& screen_size) override;
void HandlePointerEvent(const ui::LocatedEvent& event, void HandlePointerEvent(const ui::LocatedEvent& event,
const gfx::Rect& display_bounds) override; const display::Display& current_display) override;
void SetCanonicalBounds(aura::Window* container, void SetCanonicalBounds(aura::Window* container,
const gfx::Rect& display_bounds) override; const gfx::Rect& display_bounds) override;
ContainerType GetType() const override; ContainerType GetType() const override;
......
...@@ -9,6 +9,12 @@ ...@@ -9,6 +9,12 @@
#include "ui/display/screen.h" #include "ui/display/screen.h"
#include "ui/display/types/display_constants.h" #include "ui/display/types/display_constants.h"
namespace {
constexpr int kWindowMargin = 10;
} // namespace
namespace keyboard { namespace keyboard {
DisplayUtil::DisplayUtil() {} DisplayUtil::DisplayUtil() {}
...@@ -22,4 +28,45 @@ display::Display DisplayUtil::GetNearestDisplayToWindow( ...@@ -22,4 +28,45 @@ display::Display DisplayUtil::GetNearestDisplayToWindow(
return display::Screen::GetScreen()->GetDisplayNearestWindow(window); return display::Screen::GetScreen()->GetDisplayNearestWindow(window);
} }
display::Display DisplayUtil::FindAdjacentDisplayIfPointIsNearMargin(
const display::Display& current_display,
const gfx::Point& point_in_local) const {
const gfx::Rect current_bounds = current_display.bounds();
const gfx::Point point =
point_in_local + current_display.bounds().origin().OffsetFromOrigin();
int representative_x = point.x();
int representative_y = point.y();
int current_left = current_bounds.x();
int current_right = current_left + current_bounds.width();
int current_top = current_bounds.y();
int current_bottom = current_top + current_bounds.height();
// If the point is close to
if (point.x() - current_left <= kWindowMargin) {
representative_x = current_left - kWindowMargin;
} else if (current_right - point.x() <= kWindowMargin) {
representative_x = current_right + kWindowMargin;
} else if (point.y() - current_top <= kWindowMargin) {
representative_y = current_top - kWindowMargin;
} else if (current_bottom - point.y() <= kWindowMargin) {
representative_y = current_bottom + kWindowMargin;
} else {
return current_display;
}
for (const display::Display& display :
display::Screen::GetScreen()->GetAllDisplays()) {
const gfx::Rect& new_bounds = display.work_area();
if (display.touch_support() == display::Display::TouchSupport::AVAILABLE &&
display.id() != current_display.id() &&
new_bounds.Contains(representative_x, representative_y)) {
return display;
}
}
return current_display;
}
} // namespace keyboard } // namespace keyboard
...@@ -17,6 +17,9 @@ class DisplayUtil { ...@@ -17,6 +17,9 @@ class DisplayUtil {
int64_t GetNearestDisplayIdToWindow(aura::Window* window) const; int64_t GetNearestDisplayIdToWindow(aura::Window* window) const;
display::Display GetNearestDisplayToWindow(aura::Window* window) const; display::Display GetNearestDisplayToWindow(aura::Window* window) const;
display::Display FindAdjacentDisplayIfPointIsNearMargin(
const display::Display& current_display,
const gfx::Point& point) const;
}; };
} // namespace keyboard } // namespace keyboard
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "ui/keyboard/keyboard_util.h" #include "ui/keyboard/keyboard_util.h"
#include "ui/keyboard/notification_manager.h" #include "ui/keyboard/notification_manager.h"
#include "ui/keyboard/queued_container_type.h" #include "ui/keyboard/queued_container_type.h"
#include "ui/keyboard/queued_display_change.h"
#include "ui/wm/core/window_animations.h" #include "ui/wm/core/window_animations.h"
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
...@@ -336,6 +337,11 @@ void KeyboardController::RemoveObserver(KeyboardControllerObserver* observer) { ...@@ -336,6 +337,11 @@ void KeyboardController::RemoveObserver(KeyboardControllerObserver* observer) {
observer_list_.RemoveObserver(observer); observer_list_.RemoveObserver(observer);
} }
void KeyboardController::MoveToDisplayWithTransition(display::Display display) {
queued_display_change_ = std::make_unique<QueuedDisplayChange>(display);
HideKeyboard(HIDE_REASON_AUTOMATIC);
}
void KeyboardController::HideKeyboard(HideReason reason) { void KeyboardController::HideKeyboard(HideReason reason) {
TRACE_EVENT0("vk", "HideKeyboard"); TRACE_EVENT0("vk", "HideKeyboard");
...@@ -390,15 +396,22 @@ void KeyboardController::HideKeyboard(HideReason reason) { ...@@ -390,15 +396,22 @@ void KeyboardController::HideKeyboard(HideReason reason) {
} }
void KeyboardController::HideAnimationFinished() { void KeyboardController::HideAnimationFinished() {
if (state_ == KeyboardControllerState::HIDDEN && queued_container_type_) { if (state_ == KeyboardControllerState::HIDDEN) {
SetContainerBehaviorInternal(queued_container_type_->container_type()); if (queued_container_type_) {
// The position of the container window will be adjusted shortly in SetContainerBehaviorInternal(queued_container_type_->container_type());
// |PopulateKeyboardContent| before showing animation, so we can set the // The position of the container window will be adjusted shortly in
// passed bounds directly. // |PopulateKeyboardContent| before showing animation, so we can set the
if (queued_container_type_->target_bounds()) // passed bounds directly.
SetContainerBounds(queued_container_type_->target_bounds().value(), if (queued_container_type_->target_bounds())
false /* contents_loaded */); SetContainerBounds(queued_container_type_->target_bounds().value(),
ShowKeyboard(false /* lock */); false /* contents_loaded */);
ShowKeyboard(false /* lock */);
}
if (queued_display_change_) {
ShowKeyboardInDisplay(queued_display_change_->new_display().id());
queued_display_change_ = nullptr;
}
} }
} }
...@@ -780,8 +793,9 @@ bool KeyboardController::IsOverscrollAllowed() const { ...@@ -780,8 +793,9 @@ bool KeyboardController::IsOverscrollAllowed() const {
} }
void KeyboardController::HandlePointerEvent(const ui::LocatedEvent& event) { void KeyboardController::HandlePointerEvent(const ui::LocatedEvent& event) {
container_behavior_->HandlePointerEvent( const display::Display& current_display =
event, container_->GetRootWindow()->bounds()); display_util_.GetNearestDisplayToWindow(container_->GetRootWindow());
container_behavior_->HandlePointerEvent(event, current_display);
} }
void KeyboardController::SetContainerType( void KeyboardController::SetContainerType(
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "ui/keyboard/keyboard_util.h" #include "ui/keyboard/keyboard_util.h"
#include "ui/keyboard/notification_manager.h" #include "ui/keyboard/notification_manager.h"
#include "ui/keyboard/queued_container_type.h" #include "ui/keyboard/queued_container_type.h"
#include "ui/keyboard/queued_display_change.h"
namespace aura { namespace aura {
class Window; class Window;
...@@ -184,6 +185,8 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver, ...@@ -184,6 +185,8 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
// Sets floating keyboard drggable rect. // Sets floating keyboard drggable rect.
bool SetDraggableArea(const gfx::Rect& rect); bool SetDraggableArea(const gfx::Rect& rect);
void MoveToDisplayWithTransition(display::Display display);
private: private:
// For access to Observer methods for simulation. // For access to Observer methods for simulation.
friend class KeyboardControllerTest; friend class KeyboardControllerTest;
...@@ -268,6 +271,7 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver, ...@@ -268,6 +271,7 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
std::unique_ptr<ContainerBehavior> container_behavior_; std::unique_ptr<ContainerBehavior> container_behavior_;
std::unique_ptr<QueuedContainerType> queued_container_type_; std::unique_ptr<QueuedContainerType> queued_container_type_;
std::unique_ptr<QueuedDisplayChange> queued_display_change_;
// If true, show the keyboard window when keyboard UI content updates. // If true, show the keyboard window when keyboard UI content updates.
bool show_on_content_update_; bool show_on_content_update_;
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/keyboard/queued_display_change.h"
#include "base/bind.h"
#include "ui/display/display.h"
#include "ui/keyboard/keyboard_controller.h"
namespace keyboard {
QueuedDisplayChange::QueuedDisplayChange(const display::Display& display)
: new_display_(display){};
QueuedDisplayChange::~QueuedDisplayChange(){};
} // namespace keyboard
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_KEYBOARD_QUEUED_DISPLAY_CHANGE_H_
#define UI_KEYBOARD_QUEUED_DISPLAY_CHANGE_H_
#include "base/bind.h"
#include "base/optional.h"
#include "ui/display/display.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/keyboard/container_type.h"
namespace keyboard {
// TODO: refactor and merge this into QueuedContainerType and rename it to
// something like QueuedVisualChange or similar.
class QueuedDisplayChange {
public:
QueuedDisplayChange(const display::Display& display_info);
~QueuedDisplayChange();
display::Display new_display() { return new_display_; }
private:
display::Display new_display_;
};
} // namespace keyboard
#endif // UI_KEYBOARD_QUEUED_DISPLAY_CHANGE_H_
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