// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromecast/browser/gesture_router.h"
#include <utility>
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "chromecast/base/chromecast_switches.h"
namespace chromecast {
GestureRouter::GestureRouter()
: gesture_source_receiver_(this),
handler_(nullptr),
can_go_back_(false),
can_top_drag_(false),
can_right_drag_(false),
managed_mode_(GetSwitchValueBoolean(switches::kManagedMode, false)),
weak_factory_(this) {}
GestureRouter::~GestureRouter() = default;
bool GestureRouter::CanHandleGesture(GestureType gesture_type) {
switch (gesture_type) {
case GestureType::GO_BACK:
return CanGoBack();
case GestureType::TAP:
return true;
case GestureType::TAP_DOWN:
return true;
case GestureType::TOP_DRAG:
return CanTopDrag();
case GestureType::RIGHT_DRAG:
return CanRightDrag();
default:
return false;
}
}
void GestureRouter::GestureProgress(GestureType gesture_type,
const gfx::Point& touch_location) {
switch (gesture_type) {
case GestureType::GO_BACK:
if (!CanGoBack())
return;
SendBackGestureProgress(touch_location);
break;
case GestureType::TOP_DRAG:
if (!CanTopDrag())
return;
SendTopDragGestureProgress(touch_location);
break;
case GestureType::RIGHT_DRAG:
if (!CanRightDrag())
return;
SendRightDragGestureProgress(touch_location);
break;
default:
return;
}
}
void GestureRouter::CancelGesture(GestureType gesture_type) {
switch (gesture_type) {
case GestureType::GO_BACK:
if (!CanGoBack())
return;
SendBackGestureCancel();
break;
default:
return;
}
}
void GestureRouter::ConsumeGesture(GestureType gesture_type,
GestureHandledCallback handled_callback) {
switch (gesture_type) {
case GestureType::NO_GESTURE:
std::move(handled_callback).Run(false);
break;
case GestureType::GO_BACK:
if (!CanGoBack()) {
std::move(handled_callback).Run(false);
return;
}
SendBackGesture(std::move(handled_callback));
break;
case GestureType::TAP:
SendTapGesture();
std::move(handled_callback).Run(true);
break;
case GestureType::TAP_DOWN:
SendTapDownGesture();
std::move(handled_callback).Run(true);
break;
case GestureType::TOP_DRAG:
SendTopDragGestureDone();
std::move(handled_callback).Run(true);
break;
case GestureType::RIGHT_DRAG:
SendRightDragGestureDone();
std::move(handled_callback).Run(true);
break;
default:
std::move(handled_callback).Run(false);
}
}
void GestureRouter::SetConsumeGestureCallback(ConsumerCallback callback) {
consumer_callback_ = callback;
}
void GestureRouter::SetHandler(mojom::GestureHandler* handler) {
handler_ = handler;
}
void GestureRouter::Subscribe(
mojo::PendingRemote<mojom::GestureHandler> pending_handler_remote) {
if (handler_remote_.is_bound()) {
handler_remote_.reset();
}
handler_remote_.Bind(std::move(pending_handler_remote));
SetHandler(handler_remote_.get());
}
void GestureRouter::SetCanGoBack(bool can_go_back) {
can_go_back_ = can_go_back;
if (delegate_)
delegate_->SetCanGoBack(can_go_back_);
}
bool GestureRouter::CanGoBack() const {
return can_go_back_ && (consumer_callback_ || handler_);
}
void GestureRouter::SendBackGesture(
base::OnceCallback<void(bool)> was_handled_callback) {
if (consumer_callback_) {
consumer_callback_.Run(GestureType::GO_BACK,
std::move(was_handled_callback));
return;
}
if (!handler_)
return;
handler_->OnBackGesture(std::move(was_handled_callback));
}
void GestureRouter::SendBackGestureProgress(const gfx::Point& touch_location) {
if (!handler_)
return;
handler_->OnBackGestureProgress(touch_location);
}
void GestureRouter::SendBackGestureCancel() {
if (!handler_)
return;
handler_->OnBackGestureCancel();
}
void GestureRouter::SetCanTopDrag(bool can_top_drag) {
can_top_drag_ = can_top_drag;
}
bool GestureRouter::CanTopDrag() const {
return handler_ && can_top_drag_ && !managed_mode_;
}
void GestureRouter::SendTopDragGestureDone() {
if (!handler_)
return;
handler_->OnTopDragGestureDone();
}
void GestureRouter::SendTopDragGestureProgress(
const gfx::Point& touch_location) {
if (!handler_)
return;
handler_->OnTopDragGestureProgress(touch_location);
}
void GestureRouter::SetCanRightDrag(bool can_right_drag) {
can_right_drag_ = can_right_drag;
}
bool GestureRouter::CanRightDrag() const {
return handler_ && can_right_drag_;
}
void GestureRouter::SendRightDragGestureDone() {
if (!handler_)
return;
handler_->OnRightDragGestureDone();
}
void GestureRouter::SendRightDragGestureProgress(
const gfx::Point& touch_location) {
if (!handler_)
return;
handler_->OnRightDragGestureProgress(touch_location);
}
void GestureRouter::SendTapGesture() {
if (!handler_)
return;
handler_->OnTapGesture();
}
void GestureRouter::SendTapDownGesture() {
if (!handler_)
return;
handler_->OnTapDownGesture();
}
void GestureRouter::SetBackGestureDelegate(Delegate* delegate) {
delegate_ = delegate;
if (delegate_)
delegate_->SetCanGoBack(can_go_back_);
}
base::RepeatingCallback<void(mojo::PendingReceiver<mojom::GestureSource>)>
GestureRouter::GetBinder() {
return base::BindRepeating(&GestureRouter::BindGestureSource,
weak_factory_.GetWeakPtr());
}
void GestureRouter::BindGestureSource(
mojo::PendingReceiver<mojom::GestureSource> request) {
if (gesture_source_receiver_.is_bound()) {
LOG(WARNING) << "Gesture router is being re-bound.";
gesture_source_receiver_.reset();
}
gesture_source_receiver_.Bind(std::move(request));
}
} // namespace chromecast