Commit 409f7278 authored by Ryan Daum's avatar Ryan Daum Committed by Commit Bot

[chromecast] Ability to ignore but observe all touch events.

Adds a facility to stop touch events from being processed by all event
handlers and rewriters while the screen is off.

CastTouchEventGate is installed by the window manager as the first
event rewriter in the chain. When it is eanbled it will discard
all touch events, but notify registered observers that it has done so,
so the device can be woken up and touch event processing restored.

Bug: internal b/109894724
Test: unit test and manual on device
Change-Id: I82cf69d3d02f476256b28e2c3994b264fa31fc91
Reviewed-on: https://chromium-review.googlesource.com/1220166Reviewed-by: default avatarAlex Sakhartchouk <alexst@chromium.org>
Reviewed-by: default avatarKevin Schoedel <kpschoedel@chromium.org>
Commit-Queue: Ryan Daum <rdaum@chromium.org>
Cr-Commit-Position: refs/heads/master@{#590444}
parent 6eee6010
...@@ -8,6 +8,7 @@ import("//testing/test.gni") ...@@ -8,6 +8,7 @@ import("//testing/test.gni")
cast_source_set("graphics") { cast_source_set("graphics") {
sources = [ sources = [
"cast_touch_activity_observer.h",
"cast_window_manager.h", "cast_window_manager.h",
"gestures/cast_gesture_handler.cc", "gestures/cast_gesture_handler.cc",
"gestures/cast_gesture_handler.h", "gestures/cast_gesture_handler.h",
...@@ -44,6 +45,8 @@ cast_source_set("graphics") { ...@@ -44,6 +45,8 @@ cast_source_set("graphics") {
"accessibility/partial_magnification_controller.h", "accessibility/partial_magnification_controller.h",
"cast_focus_client_aura.cc", "cast_focus_client_aura.cc",
"cast_focus_client_aura.h", "cast_focus_client_aura.h",
"cast_touch_event_gate.cc",
"cast_touch_event_gate.h",
"cast_window_manager_aura.cc", "cast_window_manager_aura.cc",
"cast_window_manager_aura.h", "cast_window_manager_aura.h",
"gestures/cast_system_gesture_dispatcher.cc", "gestures/cast_system_gesture_dispatcher.cc",
...@@ -114,6 +117,7 @@ if (use_aura && !is_cast_audio_only) { ...@@ -114,6 +117,7 @@ if (use_aura && !is_cast_audio_only) {
"accessibility/accessibility_focus_ring_controller_unittest.cc", "accessibility/accessibility_focus_ring_controller_unittest.cc",
"accessibility/partial_magnification_controller_unittest.cc", "accessibility/partial_magnification_controller_unittest.cc",
"cast_focus_client_aura_test.cc", "cast_focus_client_aura_test.cc",
"cast_touch_event_gate_test.cc",
"cast_views_test.cc", "cast_views_test.cc",
"cast_window_manager_aura_test.cc", "cast_window_manager_aura_test.cc",
"gestures/cast_system_gesture_dispatcher_test.cc", "gestures/cast_system_gesture_dispatcher_test.cc",
......
// 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 CHROMECAST_GRAPHICS_CAST_TOUCH_ACTIVITY_OBSERVER_H_
#define CHROMECAST_GRAPHICS_CAST_TOUCH_ACTIVITY_OBSERVER_H_
namespace chromecast {
class CastTouchActivityObserver {
public:
virtual ~CastTouchActivityObserver() = default;
// Invoked when the window manager has touch input disabled.
virtual void OnTouchEventsDisabled(bool disabled) = 0;
// Invoked when input is disabled and an input event is received.
// Can be used by the observer to turn touch input back on.
virtual void OnTouchActivity() = 0;
};
} // namespace chromecast
#endif // CHROMECAST_GRAPHICS_CAST_TOUCH_ACTIVITY_OBSERVER_H_
// 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 "chromecast/graphics/cast_touch_event_gate.h"
#include "chromecast/graphics/cast_touch_activity_observer.h"
#include "chromecast/graphics/cast_window_manager.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
namespace chromecast {
CastTouchEventGate::CastTouchEventGate(aura::Window* root_window)
: root_window_(root_window) {
DCHECK(root_window);
root_window_->GetHost()->GetEventSource()->AddEventRewriter(this);
}
CastTouchEventGate::~CastTouchEventGate() {
root_window_->GetHost()->GetEventSource()->RemoveEventRewriter(this);
if (enabled_) {
for (auto* observer : observers_) {
observer->OnTouchEventsDisabled(false);
}
}
}
void CastTouchEventGate::AddObserver(CastTouchActivityObserver* observer) {
observers_.insert(observer);
}
void CastTouchEventGate::RemoveObserver(CastTouchActivityObserver* observer) {
observers_.erase(observer);
}
void CastTouchEventGate::SetEnabled(bool enabled) {
enabled_ = enabled;
for (auto* observer : observers_) {
observer->OnTouchEventsDisabled(enabled_);
}
}
ui::EventRewriteStatus CastTouchEventGate::RewriteEvent(
const ui::Event& event,
std::unique_ptr<ui::Event>* rewritten_event) {
if (!enabled_ || !event.IsTouchEvent())
return ui::EVENT_REWRITE_CONTINUE;
for (auto* observer : observers_) {
observer->OnTouchActivity();
}
return ui::EVENT_REWRITE_DISCARD;
}
ui::EventRewriteStatus CastTouchEventGate::NextDispatchEvent(
const ui::Event& last_event,
std::unique_ptr<ui::Event>* new_event) {
return ui::EVENT_REWRITE_DISCARD;
}
} // namespace chromecast
// 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 CHROMECAST_GRAPHICS_CAST_TOUCH_EVENT_GATE_H_
#define CHROMECAST_GRAPHICS_CAST_TOUCH_EVENT_GATE_H_
#include "base/containers/flat_set.h"
#include "ui/events/event_rewriter.h"
namespace aura {
class Window;
} // namespace aura
namespace chromecast {
class CastTouchActivityObserver;
// An event rewriter whose purpose is to discard events (when enabled). This
// class is meant to be installed as the first rewriter in the chain, to handle
// scenarios where all input needs to be disabled, such as when the device
// screen is turned off. Instances of CastTouchActivityObserver can be
// registered to receive notifications of gated events.
class CastTouchEventGate : public ui::EventRewriter {
public:
explicit CastTouchEventGate(aura::Window* root_window);
~CastTouchEventGate() override;
void SetEnabled(bool enabled);
void AddObserver(CastTouchActivityObserver* observer);
void RemoveObserver(CastTouchActivityObserver* observer);
// ui::EventRewriter implementation.
ui::EventRewriteStatus RewriteEvent(
const ui::Event& event,
std::unique_ptr<ui::Event>* rewritten_event) override;
ui::EventRewriteStatus NextDispatchEvent(
const ui::Event& last_event,
std::unique_ptr<ui::Event>* new_event) override;
private:
bool enabled_ = false;
aura::Window* root_window_;
base::flat_set<CastTouchActivityObserver*> observers_;
};
} // namespace chromecast
#endif // CHROMECAST_GRAPHICS_CAST_TOUCH_EVENT_GATE_H_
// 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 "chromecast/graphics/cast_touch_event_gate.h"
#include <memory>
#include "base/run_loop.h"
#include "chromecast/graphics/cast_touch_activity_observer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/window.h"
#include "ui/events/event_utils.h"
#include "ui/events/test/event_generator.h"
#include "ui/events/test/events_test_utils.h"
using testing::_;
using testing::AtLeast;
using testing::Eq;
namespace chromecast {
class MockEventHandler : public ui::EventHandler {
public:
~MockEventHandler() override = default;
MOCK_METHOD1(OnTouchEvent, void(ui::TouchEvent* event));
};
class MockEventGateObserver : public CastTouchActivityObserver {
public:
~MockEventGateObserver() override = default;
MOCK_METHOD1(OnTouchEventsDisabled, void(bool disabled));
MOCK_METHOD0(OnTouchActivity, void());
};
class CastTouchEventGateTest : public aura::test::AuraTestBase {
public:
~CastTouchEventGateTest() override = default;
void SetUp() override {
aura::test::AuraTestBase::SetUp();
event_gate_ = std::make_unique<CastTouchEventGate>(root_window());
event_handler_ = std::make_unique<MockEventHandler>();
root_window()->AddPreTargetHandler(event_handler_.get());
generator_ = std::make_unique<ui::test::EventGenerator>(root_window());
gate_observer_ = std::make_unique<MockEventGateObserver>();
event_gate_->AddObserver(gate_observer_.get());
}
void TearDown() override {
event_gate_.reset();
aura::test::AuraTestBase::TearDown();
}
CastTouchEventGate& event_gate() { return *event_gate_; }
MockEventGateObserver& gate_observer() { return *gate_observer_; }
MockEventHandler& mock_event_handler() { return *event_handler_; }
ui::test::EventGenerator& event_generator() { return *generator_; }
private:
std::unique_ptr<CastTouchEventGate> event_gate_;
std::unique_ptr<MockEventGateObserver> gate_observer_;
std::unique_ptr<MockEventHandler> event_handler_;
std::unique_ptr<ui::test::EventGenerator> generator_;
};
TEST_F(CastTouchEventGateTest, DisabledByDefaultTest) {
// Tap leads to 2 touch events.
EXPECT_CALL(mock_event_handler(), OnTouchEvent(_)).Times(2);
// Expect no notifications to the observer.
EXPECT_CALL(gate_observer(), OnTouchEventsDisabled(_)).Times(0);
EXPECT_CALL(gate_observer(), OnTouchActivity()).Times(0);
event_generator().GestureTapAt(gfx::Point(50, 50));
base::RunLoop().RunUntilIdle();
}
TEST_F(CastTouchEventGateTest, EnabledBlocksEvent) {
// No event should get through.
EXPECT_CALL(mock_event_handler(), OnTouchEvent(_)).Times(0);
// We should receive a notification at the observer that the gate was enabled.
EXPECT_CALL(gate_observer(), OnTouchEventsDisabled(Eq(true))).Times(1);
// Also that it was disabled at destruction.
EXPECT_CALL(gate_observer(), OnTouchEventsDisabled(Eq(false))).Times(1);
// And that the tap event was observed (multiple events)
EXPECT_CALL(gate_observer(), OnTouchActivity()).Times(AtLeast(2));
event_gate().SetEnabled(true);
event_generator().GestureTapAt(gfx::Point(50, 50));
base::RunLoop().RunUntilIdle();
}
TEST_F(CastTouchEventGateTest, EnableThenDisable) {
EXPECT_CALL(mock_event_handler(), OnTouchEvent(_)).Times(2);
EXPECT_CALL(gate_observer(), OnTouchEventsDisabled(Eq(true))).Times(1);
EXPECT_CALL(gate_observer(), OnTouchEventsDisabled(Eq(false))).Times(1);
EXPECT_CALL(gate_observer(), OnTouchActivity()).Times(AtLeast(2));
event_gate().SetEnabled(true);
event_generator().GestureTapAt(gfx::Point(50, 50));
event_gate().SetEnabled(false);
event_generator().GestureTapAt(gfx::Point(50, 50));
base::RunLoop().RunUntilIdle();
}
} // namespace chromecast
...@@ -16,6 +16,7 @@ class Event; ...@@ -16,6 +16,7 @@ class Event;
namespace chromecast { namespace chromecast {
class CastTouchActivityObserver;
class CastGestureHandler; class CastGestureHandler;
// Chromecast's window-manager interface. // Chromecast's window-manager interface.
...@@ -71,6 +72,18 @@ class CastWindowManager { ...@@ -71,6 +72,18 @@ class CastWindowManager {
// Enable/Disable color inversion. // Enable/Disable color inversion.
virtual void SetColorInversion(bool enable) = 0; virtual void SetColorInversion(bool enable) = 0;
// Enable/disable the handling of all touch events.
virtual void SetTouchInputDisabled(bool disabled) = 0;
// Add an observer for when input events occur while touch input is disabled.
virtual void AddTouchActivityObserver(
CastTouchActivityObserver* observer) = 0;
// Remove an observer for when input events occur while touch input is
// disabled.
virtual void RemoveTouchActivityObserver(
CastTouchActivityObserver* observer) = 0;
}; };
} // namespace chromecast } // namespace chromecast
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "chromecast/graphics/cast_focus_client_aura.h" #include "chromecast/graphics/cast_focus_client_aura.h"
#include "chromecast/graphics/cast_touch_activity_observer.h"
#include "chromecast/graphics/cast_touch_event_gate.h"
#include "chromecast/graphics/gestures/cast_system_gesture_event_handler.h" #include "chromecast/graphics/gestures/cast_system_gesture_event_handler.h"
#include "chromecast/graphics/gestures/side_swipe_detector.h" #include "chromecast/graphics/gestures/side_swipe_detector.h"
#include "ui/aura/client/default_capture_client.h" #include "ui/aura/client/default_capture_client.h"
...@@ -220,6 +222,11 @@ void CastWindowManagerAura::Setup() { ...@@ -220,6 +222,11 @@ void CastWindowManagerAura::Setup() {
screen_position_client_.get()); screen_position_client_.get());
window_tree_host_->Show(); window_tree_host_->Show();
// Install the CastTouchEventGate before other event rewriters. It has to be
// the first in the chain.
event_gate_ = std::make_unique<CastTouchEventGate>(root_window);
system_gesture_dispatcher_ = std::make_unique<CastSystemGestureDispatcher>(); system_gesture_dispatcher_ = std::make_unique<CastSystemGestureDispatcher>();
system_gesture_event_handler_ = system_gesture_event_handler_ =
std::make_unique<CastSystemGestureEventHandler>( std::make_unique<CastSystemGestureEventHandler>(
...@@ -237,6 +244,7 @@ void CastWindowManagerAura::TearDown() { ...@@ -237,6 +244,7 @@ void CastWindowManagerAura::TearDown() {
if (!window_tree_host_) { if (!window_tree_host_) {
return; return;
} }
event_gate_.reset();
side_swipe_detector_.reset(); side_swipe_detector_.reset();
capture_client_.reset(); capture_client_.reset();
aura::client::SetWindowParentingClient(window_tree_host_->window(), nullptr); aura::client::SetWindowParentingClient(window_tree_host_->window(), nullptr);
...@@ -302,4 +310,18 @@ CastGestureHandler* CastWindowManagerAura::GetGestureHandler() const { ...@@ -302,4 +310,18 @@ CastGestureHandler* CastWindowManagerAura::GetGestureHandler() const {
return system_gesture_dispatcher_.get(); return system_gesture_dispatcher_.get();
} }
void CastWindowManagerAura::SetTouchInputDisabled(bool disabled) {
event_gate_->SetEnabled(disabled);
}
void CastWindowManagerAura::AddTouchActivityObserver(
CastTouchActivityObserver* observer) {
event_gate_->AddObserver(observer);
}
void CastWindowManagerAura::RemoveTouchActivityObserver(
CastTouchActivityObserver* observer) {
event_gate_->RemoveObserver(observer);
}
} // namespace chromecast } // namespace chromecast
...@@ -21,6 +21,7 @@ class ScreenPositionClient; ...@@ -21,6 +21,7 @@ class ScreenPositionClient;
namespace chromecast { namespace chromecast {
class CastTouchEventGate;
class CastFocusClientAura; class CastFocusClientAura;
class CastGestureHandler; class CastGestureHandler;
class CastSystemGestureEventHandler; class CastSystemGestureEventHandler;
...@@ -75,12 +76,18 @@ class CastWindowManagerAura : public CastWindowManager, ...@@ -75,12 +76,18 @@ class CastWindowManagerAura : public CastWindowManager,
CastGestureHandler* GetGestureHandler() const; CastGestureHandler* GetGestureHandler() const;
void SetTouchInputDisabled(bool disabled) override;
void AddTouchActivityObserver(CastTouchActivityObserver* observer) override;
void RemoveTouchActivityObserver(
CastTouchActivityObserver* observer) override;
private: private:
const bool enable_input_; const bool enable_input_;
std::unique_ptr<CastWindowTreeHost> window_tree_host_; std::unique_ptr<CastWindowTreeHost> window_tree_host_;
std::unique_ptr<aura::client::DefaultCaptureClient> capture_client_; std::unique_ptr<aura::client::DefaultCaptureClient> capture_client_;
std::unique_ptr<CastFocusClientAura> focus_client_; std::unique_ptr<CastFocusClientAura> focus_client_;
std::unique_ptr<aura::client::ScreenPositionClient> screen_position_client_; std::unique_ptr<aura::client::ScreenPositionClient> screen_position_client_;
std::unique_ptr<CastTouchEventGate> event_gate_;
std::unique_ptr<CastSystemGestureDispatcher> system_gesture_dispatcher_; std::unique_ptr<CastSystemGestureDispatcher> system_gesture_dispatcher_;
std::unique_ptr<CastSystemGestureEventHandler> system_gesture_event_handler_; std::unique_ptr<CastSystemGestureEventHandler> system_gesture_event_handler_;
std::unique_ptr<SideSwipeDetector> side_swipe_detector_; std::unique_ptr<SideSwipeDetector> side_swipe_detector_;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "chromecast/graphics/cast_window_manager_default.h" #include "chromecast/graphics/cast_window_manager_default.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "chromecast/graphics/cast_touch_activity_observer.h"
namespace chromecast { namespace chromecast {
...@@ -29,4 +30,11 @@ void CastWindowManagerDefault::AddGestureHandler(CastGestureHandler* handler) {} ...@@ -29,4 +30,11 @@ void CastWindowManagerDefault::AddGestureHandler(CastGestureHandler* handler) {}
void CastWindowManagerDefault::RemoveGestureHandler( void CastWindowManagerDefault::RemoveGestureHandler(
CastGestureHandler* handler) {} CastGestureHandler* handler) {}
void CastWindowManagerDefault::SetTouchInputDisabled(bool disabled) {}
void CastWindowManagerDefault::AddTouchActivityObserver(
CastTouchActivityObserver* observer) {}
void CastWindowManagerDefault::RemoveTouchActivityObserver(
CastTouchActivityObserver* observer) {}
} // namespace chromecast } // namespace chromecast
...@@ -30,6 +30,11 @@ class CastWindowManagerDefault : public CastWindowManager { ...@@ -30,6 +30,11 @@ class CastWindowManagerDefault : public CastWindowManager {
void SetColorInversion(bool enable) override; void SetColorInversion(bool enable) override;
void SetTouchInputDisabled(bool disabled) override;
void AddTouchActivityObserver(CastTouchActivityObserver* observer) override;
void RemoveTouchActivityObserver(
CastTouchActivityObserver* observer) override;
private: private:
DISALLOW_COPY_AND_ASSIGN(CastWindowManagerDefault); DISALLOW_COPY_AND_ASSIGN(CastWindowManagerDefault);
}; };
......
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