summaryrefslogtreecommitdiffstats
path: root/components/view_manager
diff options
context:
space:
mode:
authorben <ben@chromium.org>2015-09-02 12:04:40 -0700
committerCommit bot <commit-bot@chromium.org>2015-09-02 19:05:15 +0000
commit56277a08351ced858d3a81e97f72c98dd61db6d5 (patch)
treecb3cda332e37f7eb6afa1f667cef78b6fd618b98 /components/view_manager
parentedc611a7138a34968108406b456fa3c1bed4efc9 (diff)
downloadchromium_src-56277a08351ced858d3a81e97f72c98dd61db6d5.zip
chromium_src-56277a08351ced858d3a81e97f72c98dd61db6d5.tar.gz
chromium_src-56277a08351ced858d3a81e97f72c98dd61db6d5.tar.bz2
Move FocusController to ViewTreeHost.
R=sky@chromium.org BUG=none Review URL: https://codereview.chromium.org/1321413003 Cr-Commit-Position: refs/heads/master@{#346984}
Diffstat (limited to 'components/view_manager')
-rw-r--r--components/view_manager/connection_manager.cc144
-rw-r--r--components/view_manager/connection_manager.h20
-rw-r--r--components/view_manager/event_dispatcher.cc36
-rw-r--r--components/view_manager/public/cpp/lib/view_tree_client_impl.cc2
-rw-r--r--components/view_manager/public/interfaces/view_tree.mojom2
-rw-r--r--components/view_manager/view_tree_host_connection.cc3
-rw-r--r--components/view_manager/view_tree_host_impl.cc95
-rw-r--r--components/view_manager/view_tree_host_impl.h19
-rw-r--r--components/view_manager/view_tree_impl.cc28
-rw-r--r--components/view_manager/view_tree_impl.h5
-rw-r--r--components/view_manager/view_tree_unittest.cc8
11 files changed, 181 insertions, 181 deletions
diff --git a/components/view_manager/connection_manager.cc b/components/view_manager/connection_manager.cc
index ae5ddfe..144acd8 100644
--- a/components/view_manager/connection_manager.cc
+++ b/components/view_manager/connection_manager.cc
@@ -10,7 +10,6 @@
#include "cc/quads/shared_quad_state.h"
#include "components/view_manager/client_connection.h"
#include "components/view_manager/connection_manager_delegate.h"
-#include "components/view_manager/focus_controller.h"
#include "components/view_manager/server_view.h"
#include "components/view_manager/view_coordinate_conversions.h"
#include "components/view_manager/view_tree_host_connection.h"
@@ -48,18 +47,12 @@ ConnectionManager::ConnectionManager(
next_host_id_(0),
event_dispatcher_(this),
current_change_(nullptr),
- in_destructor_(false),
- focus_controller_(new FocusController(this)) {
+ in_destructor_(false) {
}
ConnectionManager::~ConnectionManager() {
in_destructor_ = true;
- // Deleting views will attempt to advance focus. When we're being destroyed
- // that is not necessary. Additionally |focus_controller_| needs to be
- // destroyed before |host_|.
- focus_controller_.reset();
-
// Copy the HostConnectionMap because it will be mutated as the connections
// are closed.
HostConnectionMap host_connection_map(host_connection_map_);
@@ -110,9 +103,6 @@ void ConnectionManager::OnConnectionError(ClientConnection* connection) {
connection_map_.erase(connection->service()->id());
- // TODO(sky): I may want to advance focus differently if focus is in
- // |connection|.
-
// Notify remaining connections so that they can cleanup.
for (auto& pair : connection_map_) {
pair.second->service()->OnWillDestroyViewTreeImpl(
@@ -125,10 +115,6 @@ void ConnectionManager::OnHostConnectionClosed(
auto it = host_connection_map_.find(connection->view_tree_host());
DCHECK(it != host_connection_map_.end());
- // Clear focus if the focused view is in this viewport.
- if (GetRootView(GetFocusedView()) == it->first->root_view())
- SetFocusedView(nullptr);
-
// Get the ClientConnection by ViewTreeImpl ID.
ConnectionMap::iterator service_connection_it =
connection_map_.find(it->first->GetViewTree()->id());
@@ -202,22 +188,6 @@ ServerView* ConnectionManager::GetView(const ViewId& id) {
return service ? service->GetView(id) : nullptr;
}
-void ConnectionManager::SetFocusedView(ServerView* view) {
- if (!focus_controller_)
- return;
- ServerView* old_focused = GetFocusedView();
- if (old_focused == view)
- return;
- focus_controller_->SetFocusedView(view);
- OnFocusChanged(old_focused, view);
-}
-
-ServerView* ConnectionManager::GetFocusedView() {
- if (!focus_controller_)
- return nullptr;
- return focus_controller_->GetFocusedView();
-}
-
bool ConnectionManager::IsViewAttachedToRoot(const ServerView* view) const {
for (auto& pair : host_connection_map_) {
if (pair.first->IsViewAttachedToRoot(view))
@@ -267,6 +237,23 @@ const ViewTreeImpl* ConnectionManager::GetConnectionWithRoot(
return nullptr;
}
+ViewTreeHostImpl* ConnectionManager::GetViewTreeHostByView(
+ const ServerView* view) {
+ return const_cast<ViewTreeHostImpl*>(
+ static_cast<const ConnectionManager*>(this)->GetViewTreeHostByView(view));
+}
+
+const ViewTreeHostImpl* ConnectionManager::GetViewTreeHostByView(
+ const ServerView* view) const {
+ while (view && view->parent())
+ view = view->parent();
+ for (auto& pair : host_connection_map_) {
+ if (view == pair.first->root_view())
+ return pair.first;
+ }
+ return nullptr;
+}
+
ViewTreeImpl* ConnectionManager::GetEmbedRoot(ViewTreeImpl* service) {
while (service) {
const ViewId* root_id = service->root();
@@ -309,15 +296,6 @@ void ConnectionManager::RemoveAccelerator(ViewTreeHostImpl* host, uint32_t id) {
event_dispatcher_.RemoveAccelerator(id);
}
-void ConnectionManager::SetImeVisibility(ServerView* view, bool visible) {
- // Do not need to show or hide IME for unfocused view.
- if (focus_controller_->GetFocusedView() != view)
- return;
-
- ViewTreeHostImpl* host = GetViewTreeHostByView(view);
- host->SetImeVisibility(visible);
-}
-
void ConnectionManager::ProcessViewBoundsChanged(const ServerView* view,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) {
@@ -390,17 +368,6 @@ void ConnectionManager::AddConnection(ClientConnection* connection) {
connection_map_[connection->service()->id()] = connection;
}
-ViewTreeHostImpl* ConnectionManager::GetViewTreeHostByView(
- const ServerView* view) const {
- while (view && view->parent())
- view = view->parent();
- for (auto& pair : host_connection_map_) {
- if (view == pair.first->root_view())
- return pair.first;
- }
- return nullptr;
-}
-
scoped_ptr<cc::CompositorFrame>
ConnectionManager::UpdateViewTreeFromCompositorFrame(
const mojo::CompositorFramePtr& input) {
@@ -417,7 +384,7 @@ void ConnectionManager::OnScheduleViewPaint(const ServerView* view) {
}
const ServerView* ConnectionManager::GetRootView(const ServerView* view) const {
- ViewTreeHostImpl* host = GetViewTreeHostByView(view);
+ const ViewTreeHostImpl* host = GetViewTreeHostByView(view);
return host ? host->root_view() : nullptr;
}
@@ -502,79 +469,8 @@ void ConnectionManager::OnViewSharedPropertyChanged(
void ConnectionManager::OnViewTextInputStateChanged(
ServerView* view,
const ui::TextInputState& state) {
- // Do not need to update text input for unfocused views.
- if (focus_controller_->GetFocusedView() != view)
- return;
-
ViewTreeHostImpl* host = GetViewTreeHostByView(view);
- host->UpdateTextInputState(state);
-}
-
-void ConnectionManager::OnFocusChanged(ServerView* old_focused_view,
- ServerView* new_focused_view) {
- // There are up to four connections that need to be notified:
- // . the connection containing |old_focused_view|.
- // . the connection with |old_focused_view| as its root.
- // . the connection containing |new_focused_view|.
- // . the connection with |new_focused_view| as its root.
- // Some of these connections may be the same. The following takes care to
- // notify each only once.
- ViewTreeImpl* owning_connection_old = nullptr;
- ViewTreeImpl* embedded_connection_old = nullptr;
-
- if (old_focused_view) {
- owning_connection_old = GetConnection(old_focused_view->id().connection_id);
- if (owning_connection_old) {
- owning_connection_old->ProcessFocusChanged(old_focused_view,
- new_focused_view);
- }
- embedded_connection_old = GetConnectionWithRoot(old_focused_view->id());
- if (embedded_connection_old) {
- DCHECK_NE(owning_connection_old, embedded_connection_old);
- embedded_connection_old->ProcessFocusChanged(old_focused_view,
- new_focused_view);
- }
- }
- ViewTreeImpl* owning_connection_new = nullptr;
- ViewTreeImpl* embedded_connection_new = nullptr;
- if (new_focused_view) {
- owning_connection_new = GetConnection(new_focused_view->id().connection_id);
- if (owning_connection_new &&
- owning_connection_new != owning_connection_old &&
- owning_connection_new != embedded_connection_old) {
- owning_connection_new->ProcessFocusChanged(old_focused_view,
- new_focused_view);
- }
- embedded_connection_new = GetConnectionWithRoot(new_focused_view->id());
- if (embedded_connection_new &&
- embedded_connection_new != owning_connection_old &&
- embedded_connection_new != embedded_connection_old) {
- DCHECK_NE(owning_connection_new, embedded_connection_new);
- embedded_connection_new->ProcessFocusChanged(old_focused_view,
- new_focused_view);
- }
- }
-
- for (auto& pair : host_connection_map_) {
- ViewTreeImpl* service = pair.first->GetViewTree();
- if (service != owning_connection_old &&
- service != embedded_connection_old &&
- service != owning_connection_new &&
- service != embedded_connection_new) {
- service->ProcessFocusChanged(old_focused_view, new_focused_view);
- }
- }
-
- ViewTreeHostImpl* old_host =
- old_focused_view ? GetViewTreeHostByView(old_focused_view) : nullptr;
-
- ViewTreeHostImpl* new_host =
- new_focused_view ? GetViewTreeHostByView(new_focused_view) : nullptr;
-
- if (new_host)
- new_host->UpdateTextInputState(new_focused_view->text_input_state());
- else if (old_host)
- old_host->UpdateTextInputState(ui::TextInputState());
+ host->UpdateTextInputState(view, state);
}
bool ConnectionManager::ConvertSurfaceDrawQuad(
diff --git a/components/view_manager/connection_manager.h b/components/view_manager/connection_manager.h
index 49cf0fd..1eb3538 100644
--- a/components/view_manager/connection_manager.h
+++ b/components/view_manager/connection_manager.h
@@ -28,7 +28,6 @@ namespace view_manager {
class ClientConnection;
class ConnectionManagerDelegate;
-class FocusController;
class ServerView;
class ViewTreeHostConnection;
class ViewTreeImpl;
@@ -37,7 +36,6 @@ class ViewTreeImpl;
// ViewTreeImpl) as well as providing the root of the hierarchy.
class ConnectionManager : public ServerViewDelegate,
public ServerViewObserver,
- public FocusControllerDelegate,
public mojo::CustomSurfaceConverter {
public:
// Create when a ViewTreeImpl is about to make a change. Ensures clients are
@@ -118,9 +116,6 @@ class ConnectionManager : public ServerViewDelegate,
// Returns the View identified by |id|.
ServerView* GetView(const ViewId& id);
- void SetFocusedView(ServerView* view);
- ServerView* GetFocusedView();
-
// Returns whether |view| is a descendant of some root view but not itself a
// root view.
bool IsViewAttachedToRoot(const ServerView* view) const;
@@ -154,6 +149,9 @@ class ConnectionManager : public ServerViewDelegate,
}
const ViewTreeImpl* GetConnectionWithRoot(const ViewId& id) const;
+ ViewTreeHostImpl* GetViewTreeHostByView(const ServerView* view);
+ const ViewTreeHostImpl* GetViewTreeHostByView(const ServerView* view) const;
+
// Returns the first ancestor of |service| that is marked as an embed root.
ViewTreeImpl* GetEmbedRoot(ViewTreeImpl* service);
@@ -171,10 +169,6 @@ class ConnectionManager : public ServerViewDelegate,
mojo::EventFlags flags);
void RemoveAccelerator(ViewTreeHostImpl* host, uint32_t id);
- // Set IME's visibility for the specified view. If the view is not the current
- // focused view, this function will do nothing.
- void SetImeVisibility(ServerView* view, bool visible);
-
// These functions trivially delegate to all ViewTreeImpls, which in
// term notify their clients.
void ProcessViewDestroyed(ServerView* view);
@@ -218,8 +212,6 @@ class ConnectionManager : public ServerViewDelegate,
// Adds |connection| to internal maps.
void AddConnection(ClientConnection* connection);
- ViewTreeHostImpl* GetViewTreeHostByView(const ServerView* view) const;
-
// Overridden from ServerViewDelegate:
scoped_ptr<cc::CompositorFrame> UpdateViewTreeFromCompositorFrame(
const mojo::CompositorFramePtr& input) override;
@@ -249,10 +241,6 @@ class ConnectionManager : public ServerViewDelegate,
void OnViewTextInputStateChanged(ServerView* view,
const ui::TextInputState& state) override;
- // FocusControllerDelegate:
- void OnFocusChanged(ServerView* old_focused_view,
- ServerView* new_focused_view) override;
-
// Overriden from CustomSurfaceConverter:
bool ConvertSurfaceDrawQuad(const mojo::QuadPtr& input,
const mojo::CompositorFrameMetadataPtr& metadata,
@@ -284,8 +272,6 @@ class ConnectionManager : public ServerViewDelegate,
bool in_destructor_;
- scoped_ptr<FocusController> focus_controller_;
-
DISALLOW_COPY_AND_ASSIGN(ConnectionManager);
};
diff --git a/components/view_manager/event_dispatcher.cc b/components/view_manager/event_dispatcher.cc
index 3819415..3bc5477 100644
--- a/components/view_manager/event_dispatcher.cc
+++ b/components/view_manager/event_dispatcher.cc
@@ -24,12 +24,11 @@ void EventDispatcher::AddAccelerator(uint32_t id,
mojo::KeyboardCode keyboard_code,
mojo::EventFlags flags) {
#if !defined(NDEBUG)
- std::for_each(accelerators_.begin(), accelerators_.end(),
- [id, keyboard_code, flags](const Entry& entry) {
- DCHECK(entry.first != id);
- DCHECK(entry.second.keyboard_code != keyboard_code ||
- entry.second.flags != flags);
- });
+ for (const auto& pair : accelerators_) {
+ DCHECK(pair.first != id);
+ DCHECK(pair.second.keyboard_code != keyboard_code ||
+ pair.second.flags != flags);
+ }
#endif
accelerators_.insert(Entry(id, Accelerator(keyboard_code, flags)));
}
@@ -41,15 +40,17 @@ void EventDispatcher::RemoveAccelerator(uint32_t id) {
}
void EventDispatcher::OnEvent(ServerView* root, mojo::EventPtr event) {
+ ViewTreeHostImpl* host = connection_manager_->GetViewTreeHostByView(root);
+ ServerView* focused_view = host->GetFocusedView();
if (event->pointer_data) {
const gfx::Point root_point(static_cast<int>(event->pointer_data->x),
static_cast<int>(event->pointer_data->y));
- ServerView* target = connection_manager_->GetFocusedView();
+ ServerView* target = focused_view;
if (event->action == mojo::EVENT_TYPE_POINTER_DOWN || !target ||
!root->Contains(target)) {
target = FindDeepestVisibleView(root, root_point);
CHECK(target);
- connection_manager_->SetFocusedView(target);
+ host->SetFocusedView(target);
}
const gfx::PointF local_point(ConvertPointFBetweenViews(
root, target,
@@ -66,7 +67,7 @@ void EventDispatcher::OnEvent(ServerView* root, mojo::EventPtr event) {
connection_manager_->OnAccelerator(root, accelerator_id, event.Pass());
return;
}
- ServerView* focused_view = connection_manager_->GetFocusedView();
+
if (focused_view)
connection_manager_->DispatchInputEventToView(focused_view, event.Pass());
}
@@ -75,15 +76,14 @@ void EventDispatcher::OnEvent(ServerView* root, mojo::EventPtr event) {
bool EventDispatcher::HandleAccelerator(mojo::KeyboardCode keyboard_code,
mojo::EventFlags flags,
uint32_t* accelerator_id) {
- auto it = std::find_if(accelerators_.begin(), accelerators_.end(),
- [keyboard_code, flags](const Entry& entry) {
- return entry.second.keyboard_code == keyboard_code &&
- entry.second.flags == flags;
- });
- bool found = it != accelerators_.end();
- if (found)
- *accelerator_id = it->first;
- return found;
+ for (const auto& pair : accelerators_) {
+ if (pair.second.keyboard_code == keyboard_code &&
+ pair.second.flags == flags) {
+ *accelerator_id = pair.first;
+ return true;
+ }
+ }
+ return false;
}
} // namespace view_manager
diff --git a/components/view_manager/public/cpp/lib/view_tree_client_impl.cc b/components/view_manager/public/cpp/lib/view_tree_client_impl.cc
index 9639a73..216f16b 100644
--- a/components/view_manager/public/cpp/lib/view_tree_client_impl.cc
+++ b/components/view_manager/public/cpp/lib/view_tree_client_impl.cc
@@ -150,7 +150,7 @@ void ViewTreeClientImpl::SetFocus(Id view_id) {
// In order for us to get here we had to have exposed a view, which implies we
// got a connection.
DCHECK(tree_);
- tree_->SetFocus(view_id, ActionCompletedCallback());
+ tree_->SetFocus(view_id);
}
void ViewTreeClientImpl::SetVisible(Id view_id, bool visible) {
diff --git a/components/view_manager/public/interfaces/view_tree.mojom b/components/view_manager/public/interfaces/view_tree.mojom
index 1aa3b6d..008f5dc 100644
--- a/components/view_manager/public/interfaces/view_tree.mojom
+++ b/components/view_manager/public/interfaces/view_tree.mojom
@@ -139,7 +139,7 @@ interface ViewTree {
// embed roots see the complete tree at their embed point.
Embed(uint32 view_id, ViewTreeClient client) => (bool success);
- SetFocus(uint32 view_id) => (bool success);
+ SetFocus(uint32 view_id);
// Set text input state for the given view.
SetViewTextInputState(uint32 view_id, TextInputState state);
diff --git a/components/view_manager/view_tree_host_connection.cc b/components/view_manager/view_tree_host_connection.cc
index 1c9f1b5..429143c 100644
--- a/components/view_manager/view_tree_host_connection.cc
+++ b/components/view_manager/view_tree_host_connection.cc
@@ -30,6 +30,9 @@ void ViewTreeHostConnection::CloseConnection() {
// sure we signal the ConnectionManager only once.
if (connection_closed_)
return;
+ // We have to shut down the focus system for this host before destroying the
+ // host, as destruction of the view tree will attempt to change focus.
+ host_->DestroyFocusController();
connection_manager()->OnHostConnectionClosed(this);
connection_closed_ = true;
delete this;
diff --git a/components/view_manager/view_tree_host_impl.cc b/components/view_manager/view_tree_host_impl.cc
index 279dc4b..243b39c 100644
--- a/components/view_manager/view_tree_host_impl.cc
+++ b/components/view_manager/view_tree_host_impl.cc
@@ -6,8 +6,10 @@
#include "components/view_manager/connection_manager.h"
#include "components/view_manager/display_manager.h"
+#include "components/view_manager/focus_controller.h"
#include "components/view_manager/public/cpp/types.h"
#include "components/view_manager/view_tree_host_delegate.h"
+#include "components/view_manager/view_tree_impl.h"
#include "mojo/converters/geometry/geometry_type_converters.h"
namespace view_manager {
@@ -26,7 +28,8 @@ ViewTreeHostImpl::ViewTreeHostImpl(
DisplayManager::Create(is_headless,
app_impl,
gpu_state,
- surfaces_state)) {
+ surfaces_state)),
+ focus_controller_(new FocusController(this)) {
display_manager_->Init(this);
if (client_) {
client_.set_connection_error_handler(
@@ -65,13 +68,36 @@ const mojo::ViewportMetrics& ViewTreeHostImpl::GetViewportMetrics() const {
return display_manager_->GetViewportMetrics();
}
-void ViewTreeHostImpl::UpdateTextInputState(const ui::TextInputState& state) {
- if (!display_manager_)
+void ViewTreeHostImpl::SetFocusedView(ServerView* new_focused_view) {
+ ServerView* old_focused_view = focus_controller_->GetFocusedView();
+ if (old_focused_view == new_focused_view)
+ return;
+ DCHECK(root_view()->Contains(new_focused_view));
+ focus_controller_->SetFocusedView(new_focused_view);
+ // TODO(beng): have the FocusController notify us via FocusControllerDelegate.
+ OnFocusChanged(old_focused_view, new_focused_view);
+}
+
+ServerView* ViewTreeHostImpl::GetFocusedView() {
+ return focus_controller_->GetFocusedView();
+}
+
+void ViewTreeHostImpl::DestroyFocusController() {
+ focus_controller_.reset();
+}
+
+void ViewTreeHostImpl::UpdateTextInputState(ServerView* view,
+ const ui::TextInputState& state) {
+ // Do not need to update text input for unfocused views.
+ if (!display_manager_ || focus_controller_->GetFocusedView() != view)
return;
display_manager_->UpdateTextInputState(state);
}
-void ViewTreeHostImpl::SetImeVisibility(bool visible) {
+void ViewTreeHostImpl::SetImeVisibility(ServerView* view, bool visible) {
+ // Do not need to show or hide IME for unfocused view.
+ if (focus_controller_->GetFocusedView() != view)
+ return;
display_manager_->SetImeVisibility(visible);
}
@@ -129,4 +155,65 @@ void ViewTreeHostImpl::OnViewportMetricsChanged(
connection_manager_->ProcessViewportMetricsChanged(old_metrics, new_metrics);
}
+void ViewTreeHostImpl::OnFocusChanged(ServerView* old_focused_view,
+ ServerView* new_focused_view) {
+ // There are up to four connections that need to be notified:
+ // . the connection containing |old_focused_view|.
+ // . the connection with |old_focused_view| as its root.
+ // . the connection containing |new_focused_view|.
+ // . the connection with |new_focused_view| as its root.
+ // Some of these connections may be the same. The following takes care to
+ // notify each only once.
+ ViewTreeImpl* owning_connection_old = nullptr;
+ ViewTreeImpl* embedded_connection_old = nullptr;
+
+ if (old_focused_view) {
+ owning_connection_old = connection_manager_->GetConnection(
+ old_focused_view->id().connection_id);
+ if (owning_connection_old) {
+ owning_connection_old->ProcessFocusChanged(old_focused_view,
+ new_focused_view);
+ }
+ embedded_connection_old =
+ connection_manager_->GetConnectionWithRoot(old_focused_view->id());
+ if (embedded_connection_old) {
+ DCHECK_NE(owning_connection_old, embedded_connection_old);
+ embedded_connection_old->ProcessFocusChanged(old_focused_view,
+ new_focused_view);
+ }
+ }
+ ViewTreeImpl* owning_connection_new = nullptr;
+ ViewTreeImpl* embedded_connection_new = nullptr;
+ if (new_focused_view) {
+ owning_connection_new = connection_manager_->GetConnection(
+ new_focused_view->id().connection_id);
+ if (owning_connection_new &&
+ owning_connection_new != owning_connection_old &&
+ owning_connection_new != embedded_connection_old) {
+ owning_connection_new->ProcessFocusChanged(old_focused_view,
+ new_focused_view);
+ }
+ embedded_connection_new =
+ connection_manager_->GetConnectionWithRoot(new_focused_view->id());
+ if (embedded_connection_new &&
+ embedded_connection_new != owning_connection_old &&
+ embedded_connection_new != embedded_connection_old) {
+ DCHECK_NE(owning_connection_new, embedded_connection_new);
+ embedded_connection_new->ProcessFocusChanged(old_focused_view,
+ new_focused_view);
+ }
+ }
+
+ // Ensure that we always notify the root connection of a focus change.
+ ViewTreeImpl* root_tree = GetViewTree();
+ if (root_tree != owning_connection_old &&
+ root_tree != embedded_connection_old &&
+ root_tree != owning_connection_new &&
+ root_tree != embedded_connection_new) {
+ root_tree->ProcessFocusChanged(old_focused_view, new_focused_view);
+ }
+
+ UpdateTextInputState(new_focused_view, new_focused_view->text_input_state());
+}
+
} // namespace view_manager
diff --git a/components/view_manager/view_tree_host_impl.h b/components/view_manager/view_tree_host_impl.h
index 83e25ad..95a39bd 100644
--- a/components/view_manager/view_tree_host_impl.h
+++ b/components/view_manager/view_tree_host_impl.h
@@ -7,6 +7,7 @@
#include "base/memory/scoped_ptr.h"
#include "components/view_manager/display_manager.h"
+#include "components/view_manager/focus_controller_delegate.h"
#include "components/view_manager/public/cpp/types.h"
#include "components/view_manager/public/interfaces/view_tree_host.mojom.h"
#include "components/view_manager/server_view.h"
@@ -22,6 +23,7 @@ class SurfacesScheduler;
namespace view_manager {
class ConnectionManager;
+class FocusController;
class ViewTreeHostDelegate;
class ViewTreeImpl;
@@ -31,7 +33,8 @@ class ViewTreeImpl;
// closes the associated window, then this object and related state will be
// deleted.
class ViewTreeHostImpl : public DisplayManagerDelegate,
- public mojo::ViewTreeHost {
+ public mojo::ViewTreeHost,
+ public FocusControllerDelegate {
public:
// TODO(fsamuel): All these parameters are just plumbing for creating
// DisplayManagers. We should probably just store these common parameters
@@ -68,9 +71,14 @@ class ViewTreeHostImpl : public DisplayManagerDelegate,
// Returns the root ServerView of this viewport.
ServerView* root_view() { return root_.get(); }
+ const ServerView* root_view() const { return root_.get(); }
- void UpdateTextInputState(const ui::TextInputState& state);
- void SetImeVisibility(bool visible);
+ void SetFocusedView(ServerView* view);
+ ServerView* GetFocusedView();
+ void DestroyFocusController();
+
+ void UpdateTextInputState(ServerView* view, const ui::TextInputState& state);
+ void SetImeVisibility(ServerView* view, bool visible);
// ViewTreeHost:
void SetSize(mojo::SizePtr size) override;
@@ -90,11 +98,16 @@ class ViewTreeHostImpl : public DisplayManagerDelegate,
const mojo::ViewportMetrics& old_metrics,
const mojo::ViewportMetrics& new_metrics) override;
+ // FocusControllerDelegate:
+ void OnFocusChanged(ServerView* old_focused_view,
+ ServerView* new_focused_view) override;
+
ViewTreeHostDelegate* delegate_;
ConnectionManager* const connection_manager_;
mojo::ViewTreeHostClientPtr client_;
scoped_ptr<ServerView> root_;
scoped_ptr<DisplayManager> display_manager_;
+ scoped_ptr<FocusController> focus_controller_;
DISALLOW_COPY_AND_ASSIGN(ViewTreeHostImpl);
};
diff --git a/components/view_manager/view_tree_impl.cc b/components/view_manager/view_tree_impl.cc
index 12aadb7..1439c7f 100644
--- a/components/view_manager/view_tree_impl.cc
+++ b/components/view_manager/view_tree_impl.cc
@@ -10,6 +10,7 @@
#include "components/view_manager/default_access_policy.h"
#include "components/view_manager/display_manager.h"
#include "components/view_manager/server_view.h"
+#include "components/view_manager/view_tree_host_impl.h"
#include "components/view_manager/window_manager_access_policy.h"
#include "mojo/converters/geometry/geometry_type_converters.h"
#include "mojo/converters/ime/ime_type_converters.h"
@@ -59,7 +60,9 @@ void ViewTreeImpl::Init(mojo::ViewTreeClient* client, mojo::ViewTreePtr tree) {
if (root_.get())
GetUnknownViewsFrom(GetView(*root_), &to_send);
- const ServerView* focused_view = connection_manager_->GetFocusedView();
+ // TODO(beng): verify that host can actually be nullptr here.
+ ViewTreeHostImpl* host = GetHost();
+ const ServerView* focused_view = host ? host->GetFocusedView() : nullptr;
if (focused_view)
focused_view = access_policy_->GetViewForFocusChange(focused_view);
const mojo::Id focused_view_transport_id(
@@ -81,6 +84,11 @@ bool ViewTreeImpl::IsRoot(const ViewId& id) const {
return root_.get() && *root_ == id;
}
+ViewTreeHostImpl* ViewTreeImpl::GetHost() {
+ return root_.get() ?
+ connection_manager_->GetViewTreeHostByView(GetView(*root_)) : nullptr;
+}
+
void ViewTreeImpl::OnWillDestroyViewTreeImpl(
ViewTreeImpl* connection) {
if (creator_id_ == connection->id())
@@ -626,7 +634,10 @@ void ViewTreeImpl::SetImeVisibility(uint32_t view_id,
if (success) {
if (!state.is_null())
view->SetTextInputState(state.To<ui::TextInputState>());
- connection_manager_->SetImeVisibility(view, visible);
+
+ ViewTreeHostImpl* host = GetHost();
+ if (host)
+ host->SetImeVisibility(view, visible);
}
}
@@ -640,15 +651,16 @@ void ViewTreeImpl::Embed(mojo::Id transport_view_id,
callback.Run(Embed(ViewIdFromTransportId(transport_view_id), client.Pass()));
}
-void ViewTreeImpl::SetFocus(uint32_t view_id,
- const SetFocusCallback& callback) {
+void ViewTreeImpl::SetFocus(uint32_t view_id) {
ServerView* view = GetView(ViewIdFromTransportId(view_id));
- bool success = view && view->IsDrawn() && access_policy_->CanSetFocus(view);
- if (success) {
+ // TODO(beng): consider shifting non-policy drawn check logic to VTH's
+ // FocusController.
+ if (view && view->IsDrawn() && access_policy_->CanSetFocus(view)) {
ConnectionManager::ScopedChange change(this, connection_manager_, false);
- connection_manager_->SetFocusedView(view);
+ ViewTreeHostImpl* host = GetHost();
+ if (host)
+ host->SetFocusedView(view);
}
- callback.Run(success);
}
bool ViewTreeImpl::IsRootForAccessPolicy(const ViewId& id) const {
diff --git a/components/view_manager/view_tree_impl.h b/components/view_manager/view_tree_impl.h
index 3db118c..8e0dac9 100644
--- a/components/view_manager/view_tree_impl.h
+++ b/components/view_manager/view_tree_impl.h
@@ -27,6 +27,7 @@ namespace view_manager {
class AccessPolicy;
class ConnectionManager;
class ServerView;
+class ViewTreeHostImpl;
// An instance of ViewTreeImpl is created for every ViewTree request.
// ViewTreeImpl tracks all the state and views created by a client. ViewTreeImpl
@@ -64,6 +65,8 @@ class ViewTreeImpl : public mojo::ViewTree, public AccessPolicyDelegate {
bool is_embed_root() const { return is_embed_root_; }
+ ViewTreeHostImpl* GetHost();
+
// Invoked when a connection is about to be destroyed.
void OnWillDestroyViewTreeImpl(ViewTreeImpl* connection);
@@ -198,7 +201,7 @@ class ViewTreeImpl : public mojo::ViewTree, public AccessPolicyDelegate {
void Embed(mojo::Id transport_view_id,
mojo::ViewTreeClientPtr client,
const mojo::Callback<void(bool)>& callback) override;
- void SetFocus(uint32_t view_id, const SetFocusCallback& callback) override;
+ void SetFocus(uint32_t view_id) override;
void SetViewTextInputState(uint32_t view_id,
mojo::TextInputStatePtr state) override;
void SetImeVisibility(uint32_t view_id,
diff --git a/components/view_manager/view_tree_unittest.cc b/components/view_manager/view_tree_unittest.cc
index e467740..bdb67c5 100644
--- a/components/view_manager/view_tree_unittest.cc
+++ b/components/view_manager/view_tree_unittest.cc
@@ -357,9 +357,9 @@ TEST_F(ViewTreeTest, FocusOnPointer) {
connection_manager()->OnEvent(host_connection()->view_tree_host(),
CreatePointerDownEvent(21, 22));
- // Focus should go to child1. This results in notifying both the window
+ // Focus should go to child1. This result in notifying both the window
// manager and client connection being notified.
- EXPECT_EQ(v1, connection_manager()->GetFocusedView());
+ EXPECT_EQ(v1, connection1->GetHost()->GetFocusedView());
ASSERT_GE(wm_client()->tracker()->changes()->size(), 1u);
EXPECT_EQ("Focused id=2,1",
ChangesToDescription1(*wm_client()->tracker()->changes())[0]);
@@ -379,7 +379,7 @@ TEST_F(ViewTreeTest, FocusOnPointer) {
connection_manager()->OnEvent(host_connection()->view_tree_host(),
CreatePointerDownEvent(61, 22));
EXPECT_EQ(host_connection()->view_tree_host()->root_view(),
- connection_manager()->GetFocusedView());
+ host_connection()->view_tree_host()->GetFocusedView());
ASSERT_GE(wm_client()->tracker()->changes()->size(), 1u);
EXPECT_EQ("Focused id=0,2",
ChangesToDescription1(*wm_client()->tracker()->changes())[0]);
@@ -398,7 +398,7 @@ TEST_F(ViewTreeTest, FocusOnPointer) {
connection_manager()->OnEvent(host_connection()->view_tree_host(),
CreatePointerDownEvent(61, 22));
EXPECT_EQ(host_connection()->view_tree_host()->root_view(),
- connection_manager()->GetFocusedView());
+ host_connection()->view_tree_host()->GetFocusedView());
ASSERT_EQ(wm_client()->tracker()->changes()->size(), 1u);
EXPECT_EQ("InputEvent view=0,2 event_action=4",
ChangesToDescription1(*wm_client()->tracker()->changes())[0]);