[go: nahoru, domu]

chromeos: Makes WindowTreeClient install PlatformEventSource

This only works for Ozone and is necessary for both
UserActivityDetector and remoting. Long term we need to rewrite both
of these to use something else, but for now this accomplishes what
they need.

BUG=822577
TEST=covered by tests

Change-Id: I432cbdcce17bb199bf8bb0f00ec51de81d3c71f0
Reviewed-on: https://chromium-review.googlesource.com/967447
Reviewed-by: Sadrul Chowdhury <sadrul@chromium.org>
Commit-Queue: Scott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#544063}
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn
index 657b7c4c..16f8d0d 100644
--- a/ui/aura/BUILD.gn
+++ b/ui/aura/BUILD.gn
@@ -201,6 +201,10 @@
 
   if (use_ozone) {
     deps += [ "//ui/ozone" ]
+    sources += [
+      "mus/platform_event_source_mus_ozone.cc",
+      "mus/platform_event_source_mus_ozone.h",
+    ]
   }
 
   if (is_android) {
@@ -365,6 +369,7 @@
     "mus/window_port_mus_unittest.cc",
     "mus/window_tree_client_unittest.cc",
     "mus/window_tree_host_mus_unittest.cc",
+    "test/aura_test_suite.h",
     "test/run_all_unittests.cc",
     "window_event_dispatcher_unittest.cc",
     "window_occlusion_tracker_unittest.cc",
diff --git a/ui/aura/mus/platform_event_source_mus_ozone.cc b/ui/aura/mus/platform_event_source_mus_ozone.cc
new file mode 100644
index 0000000..dfd4133
--- /dev/null
+++ b/ui/aura/mus/platform_event_source_mus_ozone.cc
@@ -0,0 +1,26 @@
+// 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 "ui/aura/mus/platform_event_source_mus_ozone.h"
+
+#include "ui/events/event.h"
+#include "ui/events/platform/platform_event_observer.h"
+
+namespace aura {
+
+PlatformEventSourceMus::PlatformEventSourceMus() = default;
+
+PlatformEventSourceMus::~PlatformEventSourceMus() = default;
+
+void PlatformEventSourceMus::OnWillProcessEvent(ui::Event* event) {
+  for (ui::PlatformEventObserver& observer : observers())
+    observer.WillProcessEvent(event);
+}
+
+void PlatformEventSourceMus::OnDidProcessEvent(ui::Event* event) {
+  for (ui::PlatformEventObserver& observer : observers())
+    observer.DidProcessEvent(event);
+}
+
+}  // namespace aura
diff --git a/ui/aura/mus/platform_event_source_mus_ozone.h b/ui/aura/mus/platform_event_source_mus_ozone.h
new file mode 100644
index 0000000..8557688
--- /dev/null
+++ b/ui/aura/mus/platform_event_source_mus_ozone.h
@@ -0,0 +1,35 @@
+// 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 UI_AURA_MUS_PLATFORM_EVENT_SOURCE_MUS_OZONE_H_
+#define UI_AURA_MUS_PLATFORM_EVENT_SOURCE_MUS_OZONE_H_
+
+#include "ui/events/platform/platform_event_source.h"
+
+namespace ui {
+class Event;
+}
+
+namespace aura {
+
+// PlatformEventSource implementation for mus with ozone. WindowTreeClient owns
+// and installs this. WindowTreeClient calls this to notify observers as
+// necessary.
+class PlatformEventSourceMus : public ui::PlatformEventSource {
+ public:
+  PlatformEventSourceMus();
+  ~PlatformEventSourceMus() override;
+
+  // These two functions are called from WindowTreeClient before/after
+  // dispatching events. They forward to observers.
+  void OnWillProcessEvent(ui::Event* event);
+  void OnDidProcessEvent(ui::Event* event);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PlatformEventSourceMus);
+};
+
+}  // namespace aura
+
+#endif  // UI_AURA_MUS_PLATFORM_EVENT_SOURCE_MUS_OZONE_H_
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc
index 9eb720c..297f56b 100644
--- a/ui/aura/mus/window_tree_client.cc
+++ b/ui/aura/mus/window_tree_client.cc
@@ -70,6 +70,10 @@
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/size.h"
 
+#if defined(USE_OZONE)
+#include "ui/aura/mus/platform_event_source_mus_ozone.h"
+#endif
+
 namespace aura {
 namespace {
 
@@ -91,11 +95,21 @@
   ~EventAckHandler() override {
     base::RunLoop::RemoveNestingObserverOnCurrentThread(this);
     if (ack_callback_) {
+      NotifyPlatformEventSource();
       ack_callback_->Run(handled_ ? ui::mojom::EventResult::HANDLED
                                   : ui::mojom::EventResult::UNHANDLED);
     }
   }
 
+#if defined(USE_OZONE)
+  void SetPlatformEventSourceAndEvent(
+      PlatformEventSourceMus* platform_event_source,
+      ui::Event* event) {
+    event_ = event;
+    platform_event_source_ = platform_event_source;
+  }
+#endif
+
   void set_handled(bool handled) { handled_ = handled; }
 
   // base::RunLoop::NestingObserver:
@@ -103,14 +117,26 @@
     // Acknowledge the event immediately if a nested run loop starts.
     // Otherwise we appear unresponsive for the life of the nested run loop.
     if (ack_callback_) {
+      NotifyPlatformEventSource();
       ack_callback_->Run(ui::mojom::EventResult::HANDLED);
       ack_callback_.reset();
     }
   }
 
  private:
+  void NotifyPlatformEventSource() {
+#if defined(USE_OZONE)
+    if (platform_event_source_)
+      platform_event_source_->OnDidProcessEvent(event_);
+#endif
+  }
+
   std::unique_ptr<EventResultCallback> ack_callback_;
   bool handled_ = false;
+#if defined(USE_OZONE)
+  ui::Event* event_ = nullptr;
+  PlatformEventSourceMus* platform_event_source_ = nullptr;
+#endif
 
   DISALLOW_COPY_AND_ASSIGN(EventAckHandler);
 };
@@ -197,6 +223,7 @@
   factory->CreateWindowTree(MakeRequest(&window_tree), std::move(client),
                             automatically_create_display_roots);
   wtc->SetWindowTree(std::move(window_tree));
+  wtc->CreatePlatformEventSourceIfNecessary();
   return wtc;
 }
 
@@ -467,6 +494,13 @@
   }
 }
 
+void WindowTreeClient::CreatePlatformEventSourceIfNecessary() {
+#if defined(USE_OZONE)
+  if (!ui::PlatformEventSource::GetInstance())
+    platform_event_source_ = std::make_unique<PlatformEventSourceMus>();
+#endif
+}
+
 void WindowTreeClient::RegisterWindowMus(WindowMus* window) {
   DCHECK(windows_.find(window->server_id()) == windows_.end());
   windows_[window->server_id()] = window;
@@ -1623,7 +1657,6 @@
     }
   }
 
-  EventAckHandler ack_handler(CreateEventResultCallback(event_id));
   // TODO(moshayedi): crbug.com/617222. No need to convert to ui::MouseEvent or
   // ui::TouchEvent once we have proper support for pointer events.
   std::unique_ptr<ui::Event> mapped_event = MapEvent(*event.get());
@@ -1650,6 +1683,13 @@
     event_to_dispatch = mapped_event_with_native.get();
   }
 #endif
+  // |ack_handler| may use |event_to_dispatch| from its destructor, so it needs
+  // to be destroyed after |event_to_dispatch| is destroyed.
+  EventAckHandler ack_handler(CreateEventResultCallback(event_id));
+#if defined(USE_OZONE)
+  ack_handler.SetPlatformEventSourceAndEvent(platform_event_source_.get(),
+                                             event_to_dispatch);
+#endif
 
   WindowMus* display_root_window = GetWindowByServerId(display_root_window_id);
   if (display_root_window && event->IsLocatedEvent() &&
@@ -1669,6 +1709,11 @@
     // focused window, which may have changed by the time we process the event.
     ui::Event::DispatcherApi(event_to_dispatch).set_target(window->GetWindow());
   }
+#if defined(USE_OZONE)
+  if (platform_event_source_)
+    platform_event_source_->OnWillProcessEvent(event_to_dispatch);
+#endif
+
   GetWindowTreeHostMus(window)->SendEventToSink(event_to_dispatch);
 
   ack_handler.set_handled(event_to_dispatch->handled());
diff --git a/ui/aura/mus/window_tree_client.h b/ui/aura/mus/window_tree_client.h
index 79354cd0..bc876ae 100644
--- a/ui/aura/mus/window_tree_client.h
+++ b/ui/aura/mus/window_tree_client.h
@@ -73,6 +73,7 @@
 class InFlightFocusChange;
 class InFlightPropertyChange;
 class InFlightVisibleChange;
+class PlatformEventSourceMus;
 class MusContextFactory;
 class WindowMus;
 class WindowPortMus;
@@ -244,6 +245,9 @@
       scoped_refptr<base::SingleThreadTaskRunner> io_task_runner = nullptr,
       bool create_discardable_memory = true);
 
+  // Creates a PlatformEventSourceMus if not created yet.
+  void CreatePlatformEventSourceIfNecessary();
+
   void RegisterWindowMus(WindowMus* window);
 
   WindowMus* GetWindowByServerId(ui::Id id);
@@ -737,6 +741,10 @@
   // removed.
   bool install_drag_drop_client_ = true;
 
+#if defined(USE_OZONE)
+  std::unique_ptr<PlatformEventSourceMus> platform_event_source_;
+#endif
+
   base::WeakPtrFactory<WindowTreeClient> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(WindowTreeClient);
diff --git a/ui/aura/mus/window_tree_client_unittest.cc b/ui/aura/mus/window_tree_client_unittest.cc
index ebbc7a9..1059364 100644
--- a/ui/aura/mus/window_tree_client_unittest.cc
+++ b/ui/aura/mus/window_tree_client_unittest.cc
@@ -38,6 +38,7 @@
 #include "ui/aura/mus/window_tree_host_mus.h"
 #include "ui/aura/mus/window_tree_host_mus_init_params.h"
 #include "ui/aura/test/aura_mus_test_base.h"
+#include "ui/aura/test/aura_test_suite.h"
 #include "ui/aura/test/mus/test_window_tree.h"
 #include "ui/aura/test/mus/window_tree_client_private.h"
 #include "ui/aura/test/test_window_delegate.h"
@@ -55,6 +56,8 @@
 #include "ui/display/screen.h"
 #include "ui/events/event.h"
 #include "ui/events/event_utils.h"
+#include "ui/events/platform/platform_event_observer.h"
+#include "ui/events/platform/platform_event_source.h"
 #include "ui/events/test/test_event_handler.h"
 #include "ui/gfx/geometry/dip_util.h"
 #include "ui/gfx/geometry/rect.h"
@@ -2968,8 +2971,6 @@
             last_event->root_location());
 }
 
-namespace {
-
 class TestEmbedRootDelegate : public EmbedRootDelegate {
  public:
   TestEmbedRootDelegate() = default;
@@ -2984,8 +2985,6 @@
   DISALLOW_COPY_AND_ASSIGN(TestEmbedRootDelegate);
 };
 
-}  // namespace
-
 // Verifies we don't crash when focus changes to a window in an EmbedRoot.
 TEST_F(WindowTreeClientClientTest, ChangeFocusInEmbedRootWindow) {
   TestEmbedRootDelegate embed_root_delegate;
@@ -2997,4 +2996,84 @@
   window_tree_client()->OnWindowFocused(server_id(embed_root->window()));
 }
 
+#if defined(USE_OZONE)
+
+class TestPlatformEventObserver : public ui::PlatformEventObserver {
+ public:
+  TestPlatformEventObserver() = default;
+  ~TestPlatformEventObserver() override = default;
+
+  int will_process_count() const { return will_process_count_; }
+  int did_process_count() const { return did_process_count_; }
+  ui::EventType will_process_type() const { return will_process_type_; }
+  ui::EventType did_process_type() const { return did_process_type_; }
+
+  // PlatformEventObserver:
+  void WillProcessEvent(const ui::PlatformEvent& event) override {
+    will_process_count_++;
+    will_process_type_ = static_cast<const ui::Event*>(event)->type();
+  }
+  void DidProcessEvent(const ui::PlatformEvent& event) override {
+    did_process_count_++;
+    did_process_type_ = static_cast<const ui::Event*>(event)->type();
+  }
+
+ private:
+  int will_process_count_ = 0;
+  int did_process_count_ = 0;
+  ui::EventType will_process_type_ = ui::ET_UNKNOWN;
+  ui::EventType did_process_type_ = ui::ET_UNKNOWN;
+
+  DISALLOW_COPY_AND_ASSIGN(TestPlatformEventObserver);
+};
+
+// Base class that installs a new version of Env configured for Mus in SetUp()
+// (and installs a new version of Env configured for Local during TearDown()).
+// This is necessary as when Env is created with a Model of Local it installs
+// a PlatformEventSource, not the one that WindowTreeClient installs.
+class WindowTreeClientWmOzoneTest : public test::AuraMusWmTestBase {
+ public:
+  WindowTreeClientWmOzoneTest() = default;
+  ~WindowTreeClientWmOzoneTest() override = default;
+
+  // test::AuraMusWmTestBase:
+  void SetUp() override {
+    env_reinstaller_ = std::make_unique<test::EnvReinstaller>();
+    env_ = Env::CreateInstance(Env::Mode::MUS);
+    AuraMusWmTestBase::SetUp();
+  }
+
+  void TearDown() override {
+    AuraMusWmTestBase::TearDown();
+    env_.reset();
+    env_reinstaller_.reset();
+  }
+
+ private:
+  std::unique_ptr<test::EnvReinstaller> env_reinstaller_;
+  std::unique_ptr<Env> env_;
+
+  DISALLOW_COPY_AND_ASSIGN(WindowTreeClientWmOzoneTest);
+};
+
+// Used to verify PlatformEventSource is correctly wired up in ozone.
+TEST_F(WindowTreeClientWmOzoneTest, PlatformEventSourceInstalled) {
+  ASSERT_TRUE(ui::PlatformEventSource::GetInstance());
+  TestPlatformEventObserver test_observer;
+  ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(
+      &test_observer);
+  ui::MouseEvent event(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(),
+                       ui::EventTimeForNow(), ui::EF_NONE, 0);
+  window_tree_client()->OnWindowInputEvent(1, server_id(root_window()), 0,
+                                           ui::Id(), gfx::PointF(),
+                                           ui::Event::Clone(event), 0);
+  ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(
+      &test_observer);
+  EXPECT_EQ(1, test_observer.will_process_count());
+  EXPECT_EQ(1, test_observer.did_process_count());
+  EXPECT_EQ(ui::ET_MOUSE_MOVED, test_observer.will_process_type());
+  EXPECT_EQ(ui::ET_MOUSE_MOVED, test_observer.did_process_type());
+}
+#endif
+
 }  // namespace aura
diff --git a/ui/aura/test/aura_test_suite.h b/ui/aura/test/aura_test_suite.h
new file mode 100644
index 0000000..8e805f97
--- /dev/null
+++ b/ui/aura/test/aura_test_suite.h
@@ -0,0 +1,42 @@
+// 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 UI_AURA_TEST_AURA_TEST_SUITE_H_
+#define UI_AURA_TEST_AURA_TEST_SUITE_H_
+
+#include "base/macros.h"
+
+namespace aura {
+namespace test {
+
+// The aura test suite is configured in such a way that Env is shared across
+// all tests. If a test needs to install a fresh copy of env it can create an
+// instance of this. The constructor destroys the global instance, and the
+// destructor reinstates it.
+// Typical usage is:
+//    MyTest::SetUp() {
+//      env_reinstaller_ = std::make_unique<EnvReinstaller>();
+//      my_test_env_ = Env::CreateInstance()
+//      AuraTestBase::SetUp();
+//    }
+//    MyTest::TearDown() {
+//      AuraTestBase::TearDown();
+//      my_test_env_.reset();
+//      env_reinstaller_.reset();
+//    }
+// TODO(sky): this is ugly. Instead look into having each test install it's own
+// Env. https://crbug.com/822968
+class EnvReinstaller {
+ public:
+  EnvReinstaller();
+  ~EnvReinstaller();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(EnvReinstaller);
+};
+
+}  // namespace test
+}  // namespace aura
+
+#endif  // UI_AURA_TEST_AURA_TEST_SUITE_H_
diff --git a/ui/aura/test/mus/window_tree_client_private.cc b/ui/aura/test/mus/window_tree_client_private.cc
index cd77b24..aa81a7f 100644
--- a/ui/aura/test/mus/window_tree_client_private.cc
+++ b/ui/aura/test/mus/window_tree_client_private.cc
@@ -109,6 +109,8 @@
 void WindowTreeClientPrivate::SetWindowManagerClient(
     ui::mojom::WindowManagerClient* client) {
   tree_client_impl_->window_manager_client_ = client;
+  // Mirrors what CreateForWindowManager() does.
+  tree_client_impl_->CreatePlatformEventSourceIfNecessary();
 }
 
 bool WindowTreeClientPrivate::HasPointerWatcher() {
diff --git a/ui/aura/test/run_all_unittests.cc b/ui/aura/test/run_all_unittests.cc
index f9b7de7..e728a76 100644
--- a/ui/aura/test/run_all_unittests.cc
+++ b/ui/aura/test/run_all_unittests.cc
@@ -8,15 +8,27 @@
 #include "base/test/test_suite.h"
 #include "mojo/edk/embedder/embedder.h"
 #include "ui/aura/env.h"
+#include "ui/aura/test/aura_test_suite.h"
 #include "ui/gl/gl_surface.h"
 #include "ui/gl/test/gl_surface_test_support.h"
 
+class AuraTestSuite;
+
+namespace {
+AuraTestSuite* g_test_suite = nullptr;
+}
+
 class AuraTestSuite : public base::TestSuite {
  public:
   AuraTestSuite(int argc, char** argv) : base::TestSuite(argc, argv) {}
 
+  void DestroyEnv() { env_.reset(); }
+  void CreateEnv() { env_ = aura::Env::CreateInstance(); }
+
  protected:
   void Initialize() override {
+    DCHECK(!g_test_suite);
+    g_test_suite = this;
     base::TestSuite::Initialize();
     gl::GLSurfaceTestSupport::InitializeOneOff();
     env_ = aura::Env::CreateInstance();
@@ -25,6 +37,7 @@
   void Shutdown() override {
     env_.reset();
     base::TestSuite::Shutdown();
+    g_test_suite = nullptr;
   }
 
  private:
@@ -32,6 +45,20 @@
   DISALLOW_COPY_AND_ASSIGN(AuraTestSuite);
 };
 
+namespace aura {
+namespace test {
+
+EnvReinstaller::EnvReinstaller() {
+  g_test_suite->DestroyEnv();
+}
+
+EnvReinstaller::~EnvReinstaller() {
+  g_test_suite->CreateEnv();
+}
+
+}  // namespace test
+}  // namespace aura
+
 int main(int argc, char** argv) {
   AuraTestSuite test_suite(argc, argv);
 
diff --git a/ui/events/platform/platform_event_source.h b/ui/events/platform/platform_event_source.h
index b4e3084..ca193b33 100644
--- a/ui/events/platform/platform_event_source.h
+++ b/ui/events/platform/platform_event_source.h
@@ -78,6 +78,8 @@
   // current message-loop iteration.
   virtual uint32_t DispatchEvent(PlatformEvent platform_event);
 
+  base::ObserverList<PlatformEventObserver>& observers() { return observers_; }
+
  private:
   friend class ScopedEventDispatcher;
   friend class test::PlatformEventSourceTestAPI;