Commit aa9394e0 authored by riajiang's avatar riajiang Committed by Commit bot

mus: Add watcher for all touch events.

This is part of the touch hud app for mustash (https://codereview.chromium.org/2092343002/).

BUG=588311
TEST=views_mus_unittests

Review-Url: https://codereview.chromium.org/2125663002
Cr-Commit-Position: refs/heads/master@{#405297}
parent 98caac0f
...@@ -1165,25 +1165,35 @@ void WindowTree::SetEventObserver(mojom::EventMatcherPtr matcher, ...@@ -1165,25 +1165,35 @@ void WindowTree::SetEventObserver(mojom::EventMatcherPtr matcher,
// Do not allow key events to be observed, as a compromised app could register // Do not allow key events to be observed, as a compromised app could register
// itself as an event observer and spy on keystrokes to another app. // itself as an event observer and spy on keystrokes to another app.
if (!matcher->type_matcher) { if (!matcher->type_matcher && !matcher->pointer_kind_matcher) {
DVLOG(1) << "SetEventObserver must specify an event type."; DVLOG(1) << "SetEventObserver must specify an event type.";
return; return;
} }
const ui::mojom::EventType event_type_whitelist[] = { const ui::mojom::EventType event_type_whitelist[] = {
ui::mojom::EventType::POINTER_CANCEL, ui::mojom::EventType::POINTER_DOWN, ui::mojom::EventType::POINTER_CANCEL, ui::mojom::EventType::POINTER_DOWN,
ui::mojom::EventType::POINTER_MOVE, ui::mojom::EventType::POINTER_UP, ui::mojom::EventType::POINTER_MOVE, ui::mojom::EventType::POINTER_UP,
ui::mojom::EventType::MOUSE_EXIT, ui::mojom::EventType::WHEEL, ui::mojom::EventType::MOUSE_EXIT, ui::mojom::EventType::WHEEL,
}; };
bool allowed = false;
for (ui::mojom::EventType event_type : event_type_whitelist) { if (matcher->type_matcher) {
if (matcher->type_matcher->type == event_type) { auto iter =
allowed = true; std::find(std::begin(event_type_whitelist),
break; std::end(event_type_whitelist), matcher->type_matcher->type);
if (iter == std::end(event_type_whitelist)) {
DVLOG(1) << "SetEventObserver event type not allowed";
return;
} }
} }
if (!allowed) { if (matcher->pointer_kind_matcher) {
DVLOG(1) << "SetEventObserver event type not allowed"; ui::mojom::PointerKind pointer_kind =
return; matcher->pointer_kind_matcher->pointer_kind;
if (pointer_kind != ui::mojom::PointerKind::MOUSE &&
pointer_kind != ui::mojom::PointerKind::TOUCH &&
pointer_kind != ui::mojom::PointerKind::PEN) {
DVLOG(1) << "SetEventObserver pointer kind not allowed";
return;
}
} }
event_observer_matcher_.reset(new EventMatcher(*matcher)); event_observer_matcher_.reset(new EventMatcher(*matcher));
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "ui/views/mus/native_widget_mus.h" #include "ui/views/mus/native_widget_mus.h"
#include "ui/views/mus/screen_mus.h" #include "ui/views/mus/screen_mus.h"
#include "ui/views/pointer_watcher.h" #include "ui/views/pointer_watcher.h"
#include "ui/views/touch_event_watcher.h"
#include "ui/views/views_delegate.h" #include "ui/views/views_delegate.h"
namespace views { namespace views {
...@@ -81,6 +82,8 @@ NativeWidget* WindowManagerConnection::CreateNativeWidgetMus( ...@@ -81,6 +82,8 @@ NativeWidget* WindowManagerConnection::CreateNativeWidgetMus(
} }
void WindowManagerConnection::AddPointerWatcher(PointerWatcher* watcher) { void WindowManagerConnection::AddPointerWatcher(PointerWatcher* watcher) {
// TODO(riajiang): Support multiple event matchers (crbug.com/627146).
DCHECK(!HasTouchEventWatcher());
bool had_watcher = HasPointerWatcher(); bool had_watcher = HasPointerWatcher();
pointer_watchers_.AddObserver(watcher); pointer_watchers_.AddObserver(watcher);
if (!had_watcher) { if (!had_watcher) {
...@@ -101,6 +104,28 @@ void WindowManagerConnection::RemovePointerWatcher(PointerWatcher* watcher) { ...@@ -101,6 +104,28 @@ void WindowManagerConnection::RemovePointerWatcher(PointerWatcher* watcher) {
} }
} }
void WindowManagerConnection::AddTouchEventWatcher(TouchEventWatcher* watcher) {
// TODO(riajiang): Support multiple event matchers (crbug.com/627146).
DCHECK(!HasPointerWatcher());
bool had_watcher = HasTouchEventWatcher();
touch_event_watchers_.AddObserver(watcher);
if (!had_watcher) {
ui::mojom::EventMatcherPtr matcher = ui::mojom::EventMatcher::New();
matcher->pointer_kind_matcher = ui::mojom::PointerKindMatcher::New();
matcher->pointer_kind_matcher->pointer_kind = ui::mojom::PointerKind::TOUCH;
client_->SetEventObserver(std::move(matcher));
}
}
void WindowManagerConnection::RemoveTouchEventWatcher(
TouchEventWatcher* watcher) {
touch_event_watchers_.RemoveObserver(watcher);
if (!HasTouchEventWatcher()) {
// Last TouchEventWatcher removed, stop the event observer.
client_->SetEventObserver(nullptr);
}
}
const std::set<ui::Window*>& WindowManagerConnection::GetRoots() const { const std::set<ui::Window*>& WindowManagerConnection::GetRoots() const {
return client_->GetRoots(); return client_->GetRoots();
} }
...@@ -151,6 +176,15 @@ bool WindowManagerConnection::HasPointerWatcher() { ...@@ -151,6 +176,15 @@ bool WindowManagerConnection::HasPointerWatcher() {
return !!iterator.GetNext(); return !!iterator.GetNext();
} }
bool WindowManagerConnection::HasTouchEventWatcher() {
// Check to see if we really have any observers left. This doesn't use
// base::ObserverList<>::might_have_observers() because that returns true
// during iteration over the list even when the last observer is removed.
base::ObserverList<TouchEventWatcher>::Iterator iterator(
&touch_event_watchers_);
return !!iterator.GetNext();
}
void WindowManagerConnection::OnEmbed(ui::Window* root) {} void WindowManagerConnection::OnEmbed(ui::Window* root) {}
void WindowManagerConnection::OnDidDestroyClient(ui::WindowTreeClient* client) { void WindowManagerConnection::OnDidDestroyClient(ui::WindowTreeClient* client) {
...@@ -175,14 +209,22 @@ void WindowManagerConnection::OnEventObserved(const ui::Event& event, ...@@ -175,14 +209,22 @@ void WindowManagerConnection::OnEventObserved(const ui::Event& event,
// to store screen coordinates. Screen coordinates really should be returned // to store screen coordinates. Screen coordinates really should be returned
// separately. See http://crbug.com/608547 // separately. See http://crbug.com/608547
gfx::Point location_in_screen = event.AsLocatedEvent()->root_location(); gfx::Point location_in_screen = event.AsLocatedEvent()->root_location();
if (event.type() == ui::ET_MOUSE_PRESSED) { if (HasPointerWatcher()) {
FOR_EACH_OBSERVER(PointerWatcher, pointer_watchers_, if (event.type() == ui::ET_MOUSE_PRESSED) {
OnMousePressed(*event.AsMouseEvent(), location_in_screen, FOR_EACH_OBSERVER(PointerWatcher, pointer_watchers_,
target_widget)); OnMousePressed(*event.AsMouseEvent(),
} else if (event.type() == ui::ET_TOUCH_PRESSED) { location_in_screen, target_widget));
FOR_EACH_OBSERVER(PointerWatcher, pointer_watchers_, } else if (event.type() == ui::ET_TOUCH_PRESSED) {
OnTouchPressed(*event.AsTouchEvent(), location_in_screen, FOR_EACH_OBSERVER(PointerWatcher, pointer_watchers_,
target_widget)); OnTouchPressed(*event.AsTouchEvent(),
location_in_screen, target_widget));
}
} else if (HasTouchEventWatcher()) {
if (event.IsTouchEvent() || event.IsTouchPointerEvent()) {
FOR_EACH_OBSERVER(
TouchEventWatcher, touch_event_watchers_,
OnTouchEventObserved(*event.AsLocatedEvent(), target_widget));
}
} }
} }
......
...@@ -28,6 +28,7 @@ namespace views { ...@@ -28,6 +28,7 @@ namespace views {
class ClipboardMus; class ClipboardMus;
class NativeWidget; class NativeWidget;
class PointerWatcher; class PointerWatcher;
class TouchEventWatcher;
class ScreenMus; class ScreenMus;
namespace internal { namespace internal {
class NativeWidgetDelegate; class NativeWidgetDelegate;
...@@ -67,6 +68,9 @@ class VIEWS_MUS_EXPORT WindowManagerConnection ...@@ -67,6 +68,9 @@ class VIEWS_MUS_EXPORT WindowManagerConnection
void AddPointerWatcher(PointerWatcher* watcher); void AddPointerWatcher(PointerWatcher* watcher);
void RemovePointerWatcher(PointerWatcher* watcher); void RemovePointerWatcher(PointerWatcher* watcher);
void AddTouchEventWatcher(TouchEventWatcher* watcher);
void RemoveTouchEventWatcher(TouchEventWatcher* watcher);
const std::set<ui::Window*>& GetRoots() const; const std::set<ui::Window*>& GetRoots() const;
private: private:
...@@ -75,8 +79,9 @@ class VIEWS_MUS_EXPORT WindowManagerConnection ...@@ -75,8 +79,9 @@ class VIEWS_MUS_EXPORT WindowManagerConnection
WindowManagerConnection(shell::Connector* connector, WindowManagerConnection(shell::Connector* connector,
const shell::Identity& identity); const shell::Identity& identity);
// Returns true if there is one or more pointer watchers for this client. // Returns true if there is one or more watchers for this client.
bool HasPointerWatcher(); bool HasPointerWatcher();
bool HasTouchEventWatcher();
// ui::WindowTreeClientDelegate: // ui::WindowTreeClientDelegate:
void OnEmbed(ui::Window* root) override; void OnEmbed(ui::Window* root) override;
...@@ -93,6 +98,7 @@ class VIEWS_MUS_EXPORT WindowManagerConnection ...@@ -93,6 +98,7 @@ class VIEWS_MUS_EXPORT WindowManagerConnection
std::unique_ptr<ui::WindowTreeClient> client_; std::unique_ptr<ui::WindowTreeClient> client_;
// Must be empty on destruction. // Must be empty on destruction.
base::ObserverList<PointerWatcher, true> pointer_watchers_; base::ObserverList<PointerWatcher, true> pointer_watchers_;
base::ObserverList<TouchEventWatcher, true> touch_event_watchers_;
DISALLOW_COPY_AND_ASSIGN(WindowManagerConnection); DISALLOW_COPY_AND_ASSIGN(WindowManagerConnection);
}; };
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "ui/events/event.h" #include "ui/events/event.h"
#include "ui/views/pointer_watcher.h" #include "ui/views/pointer_watcher.h"
#include "ui/views/test/scoped_views_test_helper.h" #include "ui/views/test/scoped_views_test_helper.h"
#include "ui/views/touch_event_watcher.h"
namespace views { namespace views {
namespace { namespace {
...@@ -49,6 +50,31 @@ class TestPointerWatcher : public PointerWatcher { ...@@ -49,6 +50,31 @@ class TestPointerWatcher : public PointerWatcher {
} // namespace } // namespace
namespace {
class TestTouchEventWatcher : public TouchEventWatcher {
public:
TestTouchEventWatcher() {}
~TestTouchEventWatcher() override {}
bool touch_observed() const { return touch_observed_; }
void Reset() { touch_observed_ = false; }
// TouchEventWatcher:
void OnTouchEventObserved(const ui::LocatedEvent& event,
Widget* target) override {
touch_observed_ = true;
}
private:
bool touch_observed_ = false;
DISALLOW_COPY_AND_ASSIGN(TestTouchEventWatcher);
};
} // namespace
class WindowManagerConnectionTest : public testing::Test { class WindowManagerConnectionTest : public testing::Test {
public: public:
WindowManagerConnectionTest() {} WindowManagerConnectionTest() {}
...@@ -115,4 +141,74 @@ TEST_F(WindowManagerConnectionTest, PointerWatcher) { ...@@ -115,4 +141,74 @@ TEST_F(WindowManagerConnectionTest, PointerWatcher) {
EXPECT_FALSE(watcher1.touch_pressed()); EXPECT_FALSE(watcher1.touch_pressed());
} }
TEST_F(WindowManagerConnectionTest, TouchEventWatcher) {
base::MessageLoop message_loop(base::MessageLoop::TYPE_UI);
ScopedViewsTestHelper helper;
WindowManagerConnection* connection = WindowManagerConnection::Get();
ASSERT_TRUE(connection);
const ui::EventType kMouseType[] = {
ui::ET_MOUSE_PRESSED, ui::ET_MOUSE_DRAGGED, ui::ET_MOUSE_MOVED,
ui::ET_MOUSE_ENTERED, ui::ET_MOUSE_EXITED, ui::ET_MOUSE_RELEASED};
const ui::EventType kTouchType[] = {ui::ET_TOUCH_PRESSED, ui::ET_TOUCH_MOVED,
ui::ET_TOUCH_RELEASED,
ui::ET_TOUCH_CANCELLED};
TestTouchEventWatcher watcher1;
connection->AddTouchEventWatcher(&watcher1);
// TouchEventWatchers do not trigger for mouse events.
for (size_t i = 0; i < arraysize(kMouseType); i++) {
ui::MouseEvent mouse_event(kMouseType[i], gfx::Point(), gfx::Point(),
base::TimeTicks(), 0, 0);
ui::PointerEvent mouse_pointer_event(mouse_event);
EXPECT_TRUE(mouse_pointer_event.IsMousePointerEvent());
OnEventObserved(mouse_pointer_event);
EXPECT_FALSE(watcher1.touch_observed());
watcher1.Reset();
}
// TouchEventWatchers receive both TouchEvent and TouchPointerEvent.
for (size_t i = 0; i < arraysize(kTouchType); i++) {
ui::TouchEvent touch_event(kTouchType[i], gfx::Point(), 0,
base::TimeTicks());
EXPECT_TRUE(touch_event.IsTouchEvent());
OnEventObserved(touch_event);
EXPECT_TRUE(watcher1.touch_observed());
watcher1.Reset();
ui::PointerEvent touch_pointer_event(touch_event);
EXPECT_TRUE(touch_pointer_event.IsTouchPointerEvent());
OnEventObserved(touch_pointer_event);
EXPECT_TRUE(watcher1.touch_observed());
watcher1.Reset();
}
// Two TouchEventWatchers can both receive a single observed event.
TestTouchEventWatcher watcher2;
connection->AddTouchEventWatcher(&watcher2);
ui::TouchEvent touch_event(ui::ET_TOUCH_PRESSED, gfx::Point(), 0,
base::TimeTicks());
ui::PointerEvent touch_pointer_event(touch_event);
OnEventObserved(touch_pointer_event);
EXPECT_TRUE(watcher1.touch_observed());
EXPECT_TRUE(watcher2.touch_observed());
watcher1.Reset();
watcher2.Reset();
// Removing the first TouchEventWatcher stops sending events to it.
connection->RemoveTouchEventWatcher(&watcher1);
OnEventObserved(touch_pointer_event);
EXPECT_FALSE(watcher1.touch_observed());
EXPECT_TRUE(watcher2.touch_observed());
watcher1.Reset();
watcher2.Reset();
// Removing the last TouchEventWatcher stops sending events to it.
connection->RemoveTouchEventWatcher(&watcher2);
OnEventObserved(touch_pointer_event);
EXPECT_FALSE(watcher1.touch_observed());
EXPECT_FALSE(watcher2.touch_observed());
}
} // namespace views } // namespace views
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef UI_VIEWS_POINTER_WATCHER_H_ #ifndef UI_VIEWS_POINTER_WATCHER_H_
#define UI_VIEWS_POINTER_WATCHER_H_ #define UI_VIEWS_POINTER_WATCHER_H_
#include "base/macros.h"
#include "ui/views/views_export.h" #include "ui/views/views_export.h"
namespace gfx { namespace gfx {
...@@ -27,14 +28,19 @@ class Widget; ...@@ -27,14 +28,19 @@ class Widget;
// event.target() is always null. // event.target() is always null.
class VIEWS_EXPORT PointerWatcher { class VIEWS_EXPORT PointerWatcher {
public: public:
virtual ~PointerWatcher() {} PointerWatcher() {}
virtual void OnMousePressed(const ui::MouseEvent& event, virtual void OnMousePressed(const ui::MouseEvent& event,
const gfx::Point& location_in_screen, const gfx::Point& location_in_screen,
Widget* target) = 0; Widget* target) = 0;
virtual void OnTouchPressed(const ui::TouchEvent& event, virtual void OnTouchPressed(const ui::TouchEvent& event,
const gfx::Point& location_in_screen, const gfx::Point& location_in_screen,
Widget* target) = 0; Widget* target) = 0;
protected:
virtual ~PointerWatcher() {}
private:
DISALLOW_COPY_AND_ASSIGN(PointerWatcher);
}; };
} // namespace views } // namespace views
......
// 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.
#ifndef UI_VIEWS_TOUCH_EVENT_WATCHER_H_
#define UI_VIEWS_TOUCH_EVENT_WATCHER_H_
#include "base/macros.h"
#include "ui/views/views_export.h"
namespace gfx {
class Point;
}
namespace ui {
class LocatedEvent;
}
namespace views {
class Widget;
// An interface for read-only observation of touch events (in particular, the
// events cannot be marked as handled). Only touch pointer kind are supported.
// The |target| is the top-level widget that will receive the event, if any.
// NOTE: On mus this allows observation of events outside of windows owned
// by the current process, in which case the |target| will be null. On mus
// event.target() is always null.
class VIEWS_EXPORT TouchEventWatcher {
public:
TouchEventWatcher() {}
virtual void OnTouchEventObserved(const ui::LocatedEvent& event,
Widget* target) = 0;
protected:
virtual ~TouchEventWatcher() {}
private:
DISALLOW_COPY_AND_ASSIGN(TouchEventWatcher);
};
} // namespace views
#endif // UI_VIEWS_TOUCH_EVENT_WATCHER_H_
...@@ -299,6 +299,7 @@ ...@@ -299,6 +299,7 @@
'style/platform_style.cc', 'style/platform_style.cc',
'style/platform_style.h', 'style/platform_style.h',
'style/platform_style_mac.mm', 'style/platform_style_mac.mm',
'touch_event_watcher.h',
'view.cc', 'view.cc',
'view.h', 'view.h',
'view_constants.cc', 'view_constants.cc',
......
...@@ -8,3 +8,4 @@ ...@@ -8,3 +8,4 @@
// the resulting dynamic library. // the resulting dynamic library.
#include "ui/views/pointer_watcher.h" #include "ui/views/pointer_watcher.h"
#include "ui/views/touch_event_watcher.h"
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