Commit f72a28a6 authored by jkwang's avatar jkwang Committed by Commit Bot

Allow gaming_seat to use ozone gamepad as back-end

This patch enable gaming_seat to use ozone gamepad as back-end. It is
protected by build args. If enable_exo_ozone_gamepad is turned off,
gaming_seat will fallback use old joydev implementation.

BUG=717246

Review-Url: https://codereview.chromium.org/2900773003
Cr-Commit-Position: refs/heads/master@{#478834}
parent 57f1f0bb
...@@ -49,6 +49,10 @@ declare_args() { ...@@ -49,6 +49,10 @@ declare_args() {
enable_one_click_signin = enable_one_click_signin =
is_win || is_mac || (is_linux && !is_chromeos && !is_chromecast) is_win || is_mac || (is_linux && !is_chromeos && !is_chromecast)
# Indicates if Exo should use ozone gamepad. If this is false, exo will use
# /device/gamepad as backend.
enable_exo_ozone_gamepad = use_ozone
# Set to true to bundle all the mash related mojo services into chrome. # Set to true to bundle all the mash related mojo services into chrome.
# Specify --mash to chrome to have chrome start the mash environment. # Specify --mash to chrome to have chrome start the mash environment.
enable_package_mash_services = is_chromeos enable_package_mash_services = is_chromeos
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
import("//chrome/common/features.gni")
import("//build/config/ui.gni") import("//build/config/ui.gni")
import("//testing/test.gni") import("//testing/test.gni")
...@@ -13,7 +14,6 @@ source_set("exo") { ...@@ -13,7 +14,6 @@ source_set("exo") {
"compositor_frame_sink_holder.h", "compositor_frame_sink_holder.h",
"display.cc", "display.cc",
"display.h", "display.h",
"gaming_seat.cc",
"gaming_seat.h", "gaming_seat.h",
"keyboard.cc", "keyboard.cc",
"keyboard.h", "keyboard.h",
...@@ -71,8 +71,13 @@ source_set("exo") { ...@@ -71,8 +71,13 @@ source_set("exo") {
"//ui/wm/public", "//ui/wm/public",
] ]
if (use_ozone) { if (enable_exo_ozone_gamepad) {
defines = [ "USE_OZONE_GAMEPAD" ]
sources += [ "gaming_seat_ozone.cc" ]
deps += [ "//ui/ozone" ] deps += [ "//ui/ozone" ]
deps += [ "//ui/events/ozone:events_ozone_evdev" ]
} else {
sources += [ "gaming_seat.cc" ]
} }
if (is_chromeos) { if (is_chromeos) {
...@@ -112,7 +117,6 @@ source_set("unit_tests") { ...@@ -112,7 +117,6 @@ source_set("unit_tests") {
sources = [ sources = [
"buffer_unittest.cc", "buffer_unittest.cc",
"display_unittest.cc", "display_unittest.cc",
"gaming_seat_unittest.cc",
"keyboard_unittest.cc", "keyboard_unittest.cc",
"pointer_unittest.cc", "pointer_unittest.cc",
"shared_memory_unittest.cc", "shared_memory_unittest.cc",
...@@ -152,6 +156,14 @@ source_set("unit_tests") { ...@@ -152,6 +156,14 @@ source_set("unit_tests") {
if (use_ozone) { if (use_ozone) {
deps += [ "//ui/ozone" ] deps += [ "//ui/ozone" ]
} }
if (enable_exo_ozone_gamepad) {
sources += [
"../../ui/events/ozone/gamepad/gamepad_event.cc",
"gaming_seat_unittest.cc",
]
deps += [ "//ui/events/ozone:events_ozone_evdev" ]
}
} }
test("exo_unittests") { test("exo_unittests") {
......
...@@ -7,10 +7,6 @@ ...@@ -7,10 +7,6 @@
#include <cmath> #include <cmath>
#include "base/bind.h" #include "base/bind.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/exo/gamepad_delegate.h" #include "components/exo/gamepad_delegate.h"
#include "components/exo/gaming_seat_delegate.h" #include "components/exo/gaming_seat_delegate.h"
#include "components/exo/shell_surface.h" #include "components/exo/shell_surface.h"
...@@ -60,7 +56,7 @@ class GamingSeat::ThreadSafeGamepadChangeFetcher ...@@ -60,7 +56,7 @@ class GamingSeat::ThreadSafeGamepadChangeFetcher
create_fetcher_callback_(create_fetcher_callback), create_fetcher_callback_(create_fetcher_callback),
polling_task_runner_(task_runner), polling_task_runner_(task_runner),
origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) { origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
thread_checker_.DetachFromThread(); DETACH_FROM_THREAD(thread_checker_);
} }
// Enable or disable gamepad polling. Can be called from any thread. // Enable or disable gamepad polling. Can be called from any thread.
...@@ -79,7 +75,7 @@ class GamingSeat::ThreadSafeGamepadChangeFetcher ...@@ -79,7 +75,7 @@ class GamingSeat::ThreadSafeGamepadChangeFetcher
// Enables or disables polling. // Enables or disables polling.
void EnablePollingOnPollingThread(bool enabled) { void EnablePollingOnPollingThread(bool enabled) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
is_enabled_ = enabled; is_enabled_ = enabled;
if (is_enabled_) { if (is_enabled_) {
...@@ -96,7 +92,7 @@ class GamingSeat::ThreadSafeGamepadChangeFetcher ...@@ -96,7 +92,7 @@ class GamingSeat::ThreadSafeGamepadChangeFetcher
// Schedules the next poll on the polling thread. // Schedules the next poll on the polling thread.
void SchedulePollOnPollingThread() { void SchedulePollOnPollingThread() {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(fetcher_); DCHECK(fetcher_);
if (!is_enabled_ || has_poll_scheduled_) if (!is_enabled_ || has_poll_scheduled_)
...@@ -112,7 +108,7 @@ class GamingSeat::ThreadSafeGamepadChangeFetcher ...@@ -112,7 +108,7 @@ class GamingSeat::ThreadSafeGamepadChangeFetcher
// Polls devices for new data and posts gamepad changes back to origin thread. // Polls devices for new data and posts gamepad changes back to origin thread.
void PollOnPollingThread() { void PollOnPollingThread() {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
has_poll_scheduled_ = false; has_poll_scheduled_ = false;
if (!is_enabled_) if (!is_enabled_)
...@@ -180,7 +176,7 @@ class GamingSeat::ThreadSafeGamepadChangeFetcher ...@@ -180,7 +176,7 @@ class GamingSeat::ThreadSafeGamepadChangeFetcher
bool is_enabled_ = false; bool is_enabled_ = false;
// ThreadChecker for the polling thread. // ThreadChecker for the polling thread.
base::ThreadChecker thread_checker_; THREAD_CHECKER(thread_checker_);
DISALLOW_COPY_AND_ASSIGN(ThreadSafeGamepadChangeFetcher); DISALLOW_COPY_AND_ASSIGN(ThreadSafeGamepadChangeFetcher);
}; };
...@@ -190,20 +186,13 @@ class GamingSeat::ThreadSafeGamepadChangeFetcher ...@@ -190,20 +186,13 @@ class GamingSeat::ThreadSafeGamepadChangeFetcher
GamingSeat::GamingSeat(GamingSeatDelegate* gaming_seat_delegate, GamingSeat::GamingSeat(GamingSeatDelegate* gaming_seat_delegate,
base::SingleThreadTaskRunner* polling_task_runner) base::SingleThreadTaskRunner* polling_task_runner)
: GamingSeat(gaming_seat_delegate,
polling_task_runner,
base::Bind(CreateGamepadPlatformDataFetcher)) {}
GamingSeat::GamingSeat(GamingSeatDelegate* gaming_seat_delegate,
base::SingleThreadTaskRunner* polling_task_runner,
CreateGamepadDataFetcherCallback create_fetcher_callback)
: delegate_(gaming_seat_delegate), : delegate_(gaming_seat_delegate),
gamepad_delegates_{nullptr}, gamepad_delegates_{nullptr},
weak_ptr_factory_(this) { weak_ptr_factory_(this) {
gamepad_change_fetcher_ = new ThreadSafeGamepadChangeFetcher( gamepad_change_fetcher_ = new ThreadSafeGamepadChangeFetcher(
base::Bind(&GamingSeat::ProcessGamepadChanges, base::Bind(&GamingSeat::ProcessGamepadChanges,
weak_ptr_factory_.GetWeakPtr()), weak_ptr_factory_.GetWeakPtr()),
create_fetcher_callback, polling_task_runner); base::Bind(CreateGamepadPlatformDataFetcher), polling_task_runner);
auto* helper = WMHelper::GetInstance(); auto* helper = WMHelper::GetInstance();
helper->AddFocusObserver(this); helper->AddFocusObserver(this);
...@@ -229,7 +218,7 @@ GamingSeat::~GamingSeat() { ...@@ -229,7 +218,7 @@ GamingSeat::~GamingSeat() {
void GamingSeat::OnWindowFocused(aura::Window* gained_focus, void GamingSeat::OnWindowFocused(aura::Window* gained_focus,
aura::Window* lost_focus) { aura::Window* lost_focus) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
Surface* target = nullptr; Surface* target = nullptr;
if (gained_focus) { if (gained_focus) {
target = Surface::AsSurface(gained_focus); target = Surface::AsSurface(gained_focus);
...@@ -250,7 +239,7 @@ void GamingSeat::OnWindowFocused(aura::Window* gained_focus, ...@@ -250,7 +239,7 @@ void GamingSeat::OnWindowFocused(aura::Window* gained_focus,
void GamingSeat::ProcessGamepadChanges(int index, void GamingSeat::ProcessGamepadChanges(int index,
const device::Gamepad new_pad) { const device::Gamepad new_pad) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
bool send_frame = false; bool send_frame = false;
device::Gamepad& pad_state = pad_state_.items[index]; device::Gamepad& pad_state = pad_state_.items[index];
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include "base/containers/flat_map.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h" #include "base/sequenced_task_runner.h"
...@@ -17,6 +18,10 @@ ...@@ -17,6 +18,10 @@
#include "device/gamepad/gamepad_data_fetcher.h" #include "device/gamepad/gamepad_data_fetcher.h"
#include "ui/aura/client/focus_change_observer.h" #include "ui/aura/client/focus_change_observer.h"
#if defined(USE_OZONE_GAMEPAD)
#include "ui/events/ozone/gamepad/gamepad_observer.h"
#endif
namespace exo { namespace exo {
class GamingSeatDelegate; class GamingSeatDelegate;
class GamepadDelegate; class GamepadDelegate;
...@@ -24,29 +29,43 @@ class GamepadDelegate; ...@@ -24,29 +29,43 @@ class GamepadDelegate;
using CreateGamepadDataFetcherCallback = using CreateGamepadDataFetcherCallback =
base::Callback<std::unique_ptr<device::GamepadDataFetcher>()>; base::Callback<std::unique_ptr<device::GamepadDataFetcher>()>;
// This class represents one gaming seat, it uses a background thread // TODO(jkwang): always use ozone_gamepad when ozone is default for all Chrome
// for polling gamepad devices and notifies the corresponding GampadDelegate of // OS builds. https://crbug.com/717246
// any changes. // This class represents one gaming seat. It uses /device/gamepad or
class GamingSeat : public WMHelper::FocusObserver { // ozone/gamepad as backend and notifies corresponding GamepadDelegate of any
// gamepad changes.
class GamingSeat : public WMHelper::FocusObserver
#if defined(USE_OZONE_GAMEPAD)
,
public ui::GamepadObserver
#endif
{
public: public:
// This class will post tasks to invoke the delegate on the thread runner // This class will monitor gamepad connection changes and manage gamepad
// which is associated with the thread that is creating this instance. // returned by gaming_seat_delegate.
GamingSeat(GamingSeatDelegate* gaming_seat_delegate, GamingSeat(GamingSeatDelegate* gaming_seat_delegate,
base::SingleThreadTaskRunner* polling_task_runner); base::SingleThreadTaskRunner* polling_task_runner);
// Allows test cases to specify a CreateGamepadDataFetcherCallback that
// overrides the default GamepadPlatformDataFetcher.
GamingSeat(GamingSeatDelegate* gaming_seat_delegate,
base::SingleThreadTaskRunner* polling_task_runner,
CreateGamepadDataFetcherCallback create_fetcher_callback);
~GamingSeat() override; ~GamingSeat() override;
// Overridden WMHelper::FocusObserver: // Overridden from WMHelper::FocusObserver:
void OnWindowFocused(aura::Window* gained_focus, void OnWindowFocused(aura::Window* gained_focus,
aura::Window* lost_focus) override; aura::Window* lost_focus) override;
#if defined(USE_OZONE_GAMEPAD)
// Overridden from ui::GamepadObserver:
void OnGamepadDevicesUpdated() override;
void OnGamepadEvent(const ui::GamepadEvent& event) override;
#endif
private: private:
// The delegate that handles gamepad_added.
GamingSeatDelegate* const delegate_;
#if defined(USE_OZONE_GAMEPAD)
// Contains the delegate for each gamepad device.
base::flat_map<int, GamepadDelegate*> gamepads_;
#else
class ThreadSafeGamepadChangeFetcher; class ThreadSafeGamepadChangeFetcher;
// Processes updates of gamepad data and passes changes on to delegate. // Processes updates of gamepad data and passes changes on to delegate.
...@@ -56,9 +75,6 @@ class GamingSeat : public WMHelper::FocusObserver { ...@@ -56,9 +75,6 @@ class GamingSeat : public WMHelper::FocusObserver {
// polling thread. // polling thread.
scoped_refptr<ThreadSafeGamepadChangeFetcher> gamepad_change_fetcher_; scoped_refptr<ThreadSafeGamepadChangeFetcher> gamepad_change_fetcher_;
// The delegate that handles gamepad_added.
GamingSeatDelegate* const delegate_;
// The delegate instances that all other events are dispatched to. // The delegate instances that all other events are dispatched to.
GamepadDelegate* gamepad_delegates_[device::Gamepads::kItemsLengthCap]; GamepadDelegate* gamepad_delegates_[device::Gamepads::kItemsLengthCap];
...@@ -66,9 +82,10 @@ class GamingSeat : public WMHelper::FocusObserver { ...@@ -66,9 +82,10 @@ class GamingSeat : public WMHelper::FocusObserver {
device::Gamepads pad_state_; device::Gamepads pad_state_;
// ThreadChecker for the origin thread. // ThreadChecker for the origin thread.
base::ThreadChecker thread_checker_; THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<GamingSeat> weak_ptr_factory_; base::WeakPtrFactory<GamingSeat> weak_ptr_factory_;
#endif
DISALLOW_COPY_AND_ASSIGN(GamingSeat); DISALLOW_COPY_AND_ASSIGN(GamingSeat);
}; };
......
// 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.
#include "components/exo/gamepad_delegate.h"
#include "components/exo/gaming_seat.h"
#include "components/exo/gaming_seat_delegate.h"
#include "components/exo/shell_surface.h"
#include "components/exo/surface.h"
#include "ui/events/ozone/gamepad/gamepad_provider_ozone.h"
namespace exo {
////////////////////////////////////////////////////////////////////////////////
// GamingSeat, public:
GamingSeat::GamingSeat(GamingSeatDelegate* delegate,
base::SingleThreadTaskRunner* task_runner)
: delegate_(delegate) {
auto* helper = WMHelper::GetInstance();
helper->AddFocusObserver(this);
OnWindowFocused(helper->GetFocusedWindow(), nullptr);
}
GamingSeat::~GamingSeat() {
ui::GamepadProviderOzone::GetInstance()->RemoveGamepadObserver(this);
delegate_->OnGamingSeatDestroying(this);
// Disconnect all the gamepads.
for (auto& entry : gamepads_)
entry.second->OnRemoved();
WMHelper::GetInstance()->RemoveFocusObserver(this);
}
////////////////////////////////////////////////////////////////////////////////
// WMHelper::FocusObserver overrides:
void GamingSeat::OnWindowFocused(aura::Window* gained_focus,
aura::Window* lost_focus) {
Surface* target = nullptr;
if (gained_focus) {
target = Surface::AsSurface(gained_focus);
if (!target) {
aura::Window* top_level_window = gained_focus->GetToplevelWindow();
if (top_level_window)
target = ShellSurface::GetMainSurface(top_level_window);
}
}
bool focused = target && delegate_->CanAcceptGamepadEventsForSurface(target);
if (focused) {
ui::GamepadProviderOzone::GetInstance()->AddGamepadObserver(this);
OnGamepadDevicesUpdated();
} else {
ui::GamepadProviderOzone::GetInstance()->RemoveGamepadObserver(this);
}
}
////////////////////////////////////////////////////////////////////////////////
// ui::GamepadObserver overrides:
void GamingSeat::OnGamepadDevicesUpdated() {
std::vector<ui::InputDevice> gamepad_devices =
ui::GamepadProviderOzone::GetInstance()->GetGamepadDevices();
base::flat_map<int, GamepadDelegate*> new_gamepads;
// Copy the "still connected gamepads".
for (auto& device : gamepad_devices) {
auto it = gamepads_.find(device.id);
if (it != gamepads_.end()) {
new_gamepads[device.id] = it->second;
gamepads_.erase(it);
}
}
// Remove each disconected gamepad.
for (auto& entry : gamepads_)
entry.second->OnRemoved();
// Add each new connected gamepad.
for (auto& device : gamepad_devices) {
if (new_gamepads.find(device.id) == new_gamepads.end())
new_gamepads[device.id] = delegate_->GamepadAdded();
}
new_gamepads.swap(gamepads_);
}
void GamingSeat::OnGamepadEvent(const ui::GamepadEvent& event) {
auto it = gamepads_.find(event.device_id());
if (it == gamepads_.end())
return;
switch (event.type()) {
case ui::GamepadEventType::BUTTON:
it->second->OnButton(event.code(), event.value(), event.value());
break;
case ui::GamepadEventType::AXIS:
it->second->OnAxis(event.code(), event.value());
break;
case ui::GamepadEventType::FRAME:
it->second->OnFrame();
break;
}
}
} // namespace exo
This diff is collapsed.
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