| // Copyright 2016 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 "mojo/ui/associates/view_tree_hit_tester_client.h" |
| |
| #include "base/bind.h" |
| #include "base/logging.h" |
| |
| namespace mojo { |
| namespace ui { |
| |
| ViewTreeHitTesterClient::ViewTreeHitTesterClient( |
| const scoped_refptr<ViewInspectorClient>& view_inspector_client, |
| mojo::ui::ViewTreeTokenPtr view_tree_token) |
| : view_inspector_client_(view_inspector_client), |
| view_tree_token_(view_tree_token.Pass()), |
| weak_factory_(this) { |
| DCHECK(view_inspector_client_); |
| DCHECK(view_tree_token_); |
| |
| UpdateHitTester(); |
| } |
| |
| ViewTreeHitTesterClient::~ViewTreeHitTesterClient() {} |
| |
| void ViewTreeHitTesterClient::HitTest(mojo::PointFPtr point, |
| const ResolvedHitsCallback& callback) { |
| if (!hit_tester_) { |
| callback.Run(nullptr); |
| return; |
| } |
| |
| // TODO(jeffbrown): Here we are assuming that the hit test callbacks will be |
| // invoked in FIFO order. It might be a good idea to eliminate that |
| // assumption. |
| pending_callbacks_.push(callback); |
| hit_tester_->HitTest(point.Pass(), |
| base::Bind(&ViewTreeHitTesterClient::OnHitTestResult, |
| base::Unretained(this))); |
| } |
| |
| void ViewTreeHitTesterClient::OnHitTestResult( |
| mojo::gfx::composition::HitTestResultPtr result) { |
| DCHECK(result); |
| DCHECK(!pending_callbacks_.empty()); |
| |
| view_inspector_client_->ResolveHits(result.Pass(), |
| pending_callbacks_.front()); |
| pending_callbacks_.pop(); |
| } |
| |
| void ViewTreeHitTesterClient::UpdateHitTester() { |
| DCHECK(!hit_tester_); |
| |
| view_inspector_client_->view_inspector()->GetHitTester( |
| view_tree_token_.Clone(), mojo::GetProxy(&hit_tester_), |
| base::Bind(&ViewTreeHitTesterClient::OnHitTesterInvalidated, |
| weak_factory_.GetWeakPtr())); |
| |
| hit_tester_.set_connection_error_handler(base::Bind( |
| &ViewTreeHitTesterClient::OnHitTesterDied, base::Unretained(this))); |
| } |
| |
| void ViewTreeHitTesterClient::ReleaseHitTester() { |
| hit_tester_.reset(); |
| |
| while (!pending_callbacks_.empty()) { |
| pending_callbacks_.front().Run(nullptr); |
| pending_callbacks_.pop(); |
| } |
| } |
| |
| void ViewTreeHitTesterClient::OnHitTesterInvalidated(bool renderer_changed) { |
| ReleaseHitTester(); |
| |
| if (renderer_changed) |
| UpdateHitTester(); |
| |
| if (!hit_tester_changed_callback_.is_null()) |
| hit_tester_changed_callback_.Run(); |
| } |
| |
| void ViewTreeHitTesterClient::OnHitTesterDied() { |
| ReleaseHitTester(); |
| |
| if (!hit_tester_changed_callback_.is_null()) |
| hit_tester_changed_callback_.Run(); |
| } |
| |
| } // namespace ui |
| } // namespace mojo |