blob: 42bdf9a08c459945c75e72c6232d37b61c2056be [file] [log] [blame]
// Copyright 2017 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 CHROME_BROWSER_VR_UI_INPUT_MANAGER_H_
#define CHROME_BROWSER_VR_UI_INPUT_MANAGER_H_
#include <memory>
#include <vector>
#include "base/time/time.h"
#include "chrome/browser/vr/vr_export.h"
#include "ui/gfx/geometry/point3_f.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/vector3d_f.h"
#include "ui/gfx/transform.h"
namespace blink {
class WebGestureEvent;
}
namespace vr {
class UiScene;
class UiElement;
struct ControllerModel;
struct RenderInfo;
struct ReticleModel;
struct EditedText;
using GestureList = std::vector<std::unique_ptr<blink::WebGestureEvent>>;
// Based on controller input finds the hit UI element and determines the
// interaction with UI elements and the web contents.
class VR_EXPORT UiInputManager {
public:
enum ButtonState {
UP, // The button is released.
DOWN, // The button is pressed.
};
// When testing, it can be useful to hit test directly along the laser.
// Updating the strategy permits this behavior, but it should not be used in
// production. In production, we hit test along a ray that extends from the
// world origin to a point far along the laser.
enum HitTestStrategy {
PROJECT_TO_WORLD_ORIGIN,
PROJECT_TO_LASER_ORIGIN_FOR_TEST,
};
explicit UiInputManager(UiScene* scene);
~UiInputManager();
// TODO(tiborg): Use generic gesture type instead of blink::WebGestureEvent.
void HandleInput(base::TimeTicks current_time,
const RenderInfo& render_info,
const ControllerModel& controller_model,
ReticleModel* reticle_model,
GestureList* gesture_list);
void OnPause();
// Text input related.
void RequestFocus(int element_id);
void RequestUnfocus(int element_id);
void OnInputEdited(const EditedText& info);
void OnInputCommitted(const EditedText& info);
void OnKeyboardHidden();
bool controller_quiescent() const { return controller_quiescent_; }
bool controller_resting_in_viewport() const {
return controller_resting_in_viewport_;
}
void set_hit_test_strategy(HitTestStrategy strategy) {
hit_test_strategy_ = strategy;
}
private:
void SendFlingCancel(GestureList* gesture_list,
const gfx::PointF& target_point);
void SendScrollEnd(GestureList* gesture_list,
const gfx::PointF& target_point,
ButtonState button_state);
void SendScrollBegin(UiElement* target,
GestureList* gesture_list,
const gfx::PointF& target_point);
void SendScrollUpdate(GestureList* gesture_list,
const gfx::PointF& target_point);
void SendHoverLeave(UiElement* current_target);
void SendHoverEnter(UiElement* target, const gfx::PointF& target_point);
void SendHoverMove(UiElement* target, const gfx::PointF& target_point);
void SendButtonUp(const gfx::PointF& target_point, ButtonState button_state);
void SendButtonDown(UiElement* target,
const gfx::PointF& target_point,
ButtonState button_state);
void SendTouchMove(const gfx::PointF& target_point);
UiElement* GetTargetElement(const ControllerModel& controller_model,
ReticleModel* reticle_model,
const GestureList& gesture_list) const;
void UpdateQuiescenceState(base::TimeTicks current_time,
const ControllerModel& controller_model);
void UpdateControllerFocusState(base::TimeTicks current_time,
const RenderInfo& render_info,
const ControllerModel& controller_model);
void UnfocusFocusedElement();
gfx::PointF GetCapturedElementHitPoint(
const gfx::Point3F& target_point) const;
UiScene* scene_;
int hover_target_id_ = 0;
// TODO(mthiesse): We shouldn't have a fling target. Elements should fling
// independently and we should only cancel flings on the relevant element
// when we do cancel flings.
int fling_target_id_ = 0;
int input_capture_element_id_ = 0;
int focused_element_id_ = 0;
bool in_click_ = false;
bool in_scroll_ = false;
HitTestStrategy hit_test_strategy_ = HitTestStrategy::PROJECT_TO_WORLD_ORIGIN;
ButtonState previous_button_state_ = ButtonState::UP;
base::TimeTicks last_significant_controller_update_time_;
gfx::Transform last_significant_controller_transform_;
bool controller_quiescent_ = false;
base::TimeTicks last_controller_outside_viewport_time_;
bool controller_resting_in_viewport_ = false;
};
} // namespace vr
#endif // CHROME_BROWSER_VR_UI_INPUT_MANAGER_H_