Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(559)

Side by Side Diff: components/exo/gamepad.cc

Issue 2076013002: exo: Implement wayland gamepad support (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@serv
Patch Set: fixed nits. only sends gamepad updates if an exo window is in focus. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/exo/gamepad.h"
6
7 #include <cmath>
8
9 #include "ash/shell.h"
10 #include "base/bind.h"
11 #include "base/location.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/threading/thread.h"
14 #include "base/threading/thread_task_runner_handle.h"
15 #include "components/exo/gamepad_delegate.h"
16 #include "components/exo/shell_surface.h"
17 #include "components/exo/surface.h"
18 #include "device/gamepad/gamepad_data_fetcher.h"
19 #include "device/gamepad/gamepad_platform_data_fetcher.h"
20 #include "ui/aura/client/focus_client.h"
21 #include "ui/aura/window.h"
22
23 namespace exo {
24 namespace {
25
26 constexpr double kGamepadButtonValueEpsilon = 0.001;
27 bool GamepadButtonValuesAreEqual(double a, double b) {
28 return fabs(a - b) < kGamepadButtonValueEpsilon;
29 }
30
31 // Time between gamepad polls in milliseconds.
32 constexpr unsigned kPollingTimeDelta = 16;
reveman 2016/06/30 01:19:05 nit: s/TimeDelta/Interval/? Chromium usually adds
denniskempin 2016/06/30 03:23:43 Unfortunately we cannot do anything about this, wi
denniskempin 2016/06/30 17:08:29 Done on the nit.
33
34 } // namespace
35
36 ////////////////////////////////////////////////////////////////////////////////
37 // Gamepad, public:
38
39 Gamepad::Gamepad(GamepadDelegate* delegate) : Gamepad(delegate, nullptr) {}
40
41 Gamepad::Gamepad(GamepadDelegate* delegate,
42 std::unique_ptr<device::GamepadDataFetcher> fetcher)
43 : delegate_(delegate),
44 fetcher_(std::move(fetcher)),
45 polling_thread_(new base::Thread("Exo gamepad polling thread")),
46 exo_focused_(false),
reveman 2016/06/30 01:19:05 nit: all exo code is now providing default init of
denniskempin 2016/06/30 17:08:29 Done.
47 origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
48 aura::client::FocusClient* focus_client =
49 aura::client::GetFocusClient(ash::Shell::GetPrimaryRootWindow());
50 focus_client->AddObserver(this);
51 OnWindowFocused(focus_client->GetFocusedWindow(), nullptr);
52
53 polling_thread_->StartWithOptions(
54 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
55 polling_thread_->task_runner()->PostTask(
56 FROM_HERE,
57 base::Bind(&Gamepad::InitializePollingThread, base::Unretained(this)));
58 }
59
60 Gamepad::~Gamepad() {
61 delegate_->OnGamepadDestroying(this);
62 polling_thread_->Stop();
63 }
64
65 ////////////////////////////////////////////////////////////////////////////////
66 // aura::client::FocusChangeObserver overrides:
67
68 void Gamepad::OnWindowFocused(aura::Window* gained_focus,
69 aura::Window* lost_focus) {
70 base::AutoLock _l(lock_);
reveman 2016/06/30 01:19:05 nit: base::AutoLock lock(lock_); It's hard to fol
denniskempin 2016/06/30 03:23:43 I am not quite sure how that would look like. Even
denniskempin 2016/06/30 04:56:46 Actually I take that back. I thought a bit about i
denniskempin 2016/06/30 17:08:29 Done.
71
72 Surface* target = Surface::AsSurface(gained_focus);
73 if (!target) {
74 aura::Window* top_level_window = gained_focus->GetToplevelWindow();
75 if (top_level_window)
76 target = ShellSurface::GetMainSurface(top_level_window);
77 }
78 exo_focused_ = (target != nullptr);
79 }
80
81 ////////////////////////////////////////////////////////////////////////////////
82 // Gamepad, private:
83
84 void Gamepad::ScheduleOnPoll() {
85 polling_thread_->task_runner()->PostDelayedTask(
86 FROM_HERE, base::Bind(&Gamepad::OnPoll, base::Unretained(this)),
87 base::TimeDelta::FromMilliseconds(kPollingTimeDelta));
88 }
89
90 void Gamepad::InitializePollingThread() {
91 DCHECK(base::MessageLoop::current() == polling_thread_->message_loop());
92 // The platform data fetcher has to be initialized on the polling thread.
93 if (!fetcher_)
94 fetcher_.reset(new device::GamepadPlatformDataFetcher());
95 ScheduleOnPoll();
96 }
97
98 void Gamepad::OnPoll() {
99 DCHECK(base::MessageLoop::current() == polling_thread_->message_loop());
100 DCHECK(fetcher_);
101
102 blink::WebGamepads new_state = state_;
103 fetcher_->GetGamepadData(&new_state, false);
104
105 {
106 // Lock only needed for access to exo_focused_
107 base::AutoLock _l(lock_);
108
109 if (!exo_focused_) {
110 // Keep polling but do not post changes until we are back in focus.
111 // Once back in focus, the delta between state_ and new_state will update
112 // the client to the current state of the gamepad.
113 ScheduleOnPoll();
114 return;
115 }
116 }
117
118 PostGamepadChanges(new_state);
119
120 state_ = new_state;
121 ScheduleOnPoll();
122 }
123
124 void Gamepad::PostGamepadChanges(const blink::WebGamepads new_state) {
125 DCHECK(base::MessageLoop::current() == polling_thread_->message_loop());
126
127 if (std::max(new_state.length, state_.length) == 0)
128 return;
129
130 bool send_frame = false;
131 const blink::WebGamepad& new_pad = new_state.items[0];
132 blink::WebGamepad& pad = state_.items[0];
133
134 // Update connection state.
135 if (new_pad.connected != pad.connected) {
136 origin_task_runner_->PostTask(
137 FROM_HERE, base::Bind(&GamepadDelegate::OnStateChange,
138 delegate_->GetWeakPtr(), new_pad.connected));
reveman 2016/06/30 01:19:05 GetWeakPtr() can't be called and the weak ptr retu
denniskempin 2016/06/30 17:08:29 no longer needed
139 }
140
141 if (!new_pad.connected || new_pad.timestamp <= pad.timestamp)
142 return;
143
144 // Notify delegate of updated axes.
145 for (size_t axis = 0; axis < std::max(pad.axesLength, new_pad.axesLength);
146 ++axis) {
147 if (!GamepadButtonValuesAreEqual(new_pad.axes[axis], pad.axes[axis])) {
148 send_frame = true;
149 origin_task_runner_->PostTask(
150 FROM_HERE,
151 base::Bind(&GamepadDelegate::OnAxis, delegate_->GetWeakPtr(), axis,
152 new_pad.axes[axis]));
153 }
154 }
155
156 // Notify delegate of updated buttons.
157 for (size_t button = 0;
158 button < std::max(pad.buttonsLength, new_pad.buttonsLength); ++button) {
159 if (pad.buttons[button].pressed != new_pad.buttons[button].pressed ||
160 !GamepadButtonValuesAreEqual(new_pad.buttons[button].value,
161 pad.buttons[button].value)) {
162 send_frame = true;
163 origin_task_runner_->PostTask(
164 FROM_HERE,
165 base::Bind(&GamepadDelegate::OnButton, delegate_->GetWeakPtr(),
166 button, new_pad.buttons[button].pressed,
167 new_pad.buttons[button].value));
168 }
169 }
170 if (send_frame) {
171 origin_task_runner_->PostTask(
172 FROM_HERE,
173 base::Bind(&GamepadDelegate::OnFrame, delegate_->GetWeakPtr()));
174 }
175 }
176
177 } // namespace exo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698