| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/exo/gaming_seat.h" | 5 #include "components/exo/gaming_seat_joydev.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/location.h" | |
| 11 #include "base/single_thread_task_runner.h" | |
| 12 #include "base/threading/thread.h" | |
| 13 #include "base/threading/thread_task_runner_handle.h" | |
| 14 #include "components/exo/gamepad_delegate.h" | 10 #include "components/exo/gamepad_delegate.h" |
| 15 #include "components/exo/gaming_seat_delegate.h" | 11 #include "components/exo/gaming_seat_delegate.h" |
| 16 #include "components/exo/shell_surface.h" | 12 #include "components/exo/shell_surface.h" |
| 17 #include "components/exo/surface.h" | 13 #include "components/exo/surface.h" |
| 18 #include "device/gamepad/gamepad_data_fetcher.h" | 14 #include "device/gamepad/gamepad_data_fetcher.h" |
| 19 #include "device/gamepad/gamepad_pad_state_provider.h" | 15 #include "device/gamepad/gamepad_pad_state_provider.h" |
| 20 #include "device/gamepad/gamepad_platform_data_fetcher_linux.h" | 16 #include "device/gamepad/gamepad_platform_data_fetcher_linux.h" |
| 21 #include "ui/aura/window.h" | 17 #include "ui/aura/window.h" |
| 22 | 18 |
| 23 namespace exo { | 19 namespace exo { |
| 24 namespace { | 20 namespace { |
| 25 | 21 |
| 26 constexpr double kGamepadButtonValueEpsilon = 0.001; | 22 constexpr double kGamepadButtonValueEpsilon = 0.001; |
| 27 bool GamepadButtonValuesAreEqual(double a, double b) { | 23 bool GamepadButtonValuesAreEqual(double a, double b) { |
| 28 return fabs(a - b) < kGamepadButtonValueEpsilon; | 24 return fabs(a - b) < kGamepadButtonValueEpsilon; |
| 29 } | 25 } |
| 30 | 26 |
| 31 std::unique_ptr<device::GamepadDataFetcher> CreateGamepadPlatformDataFetcher() { | 27 std::unique_ptr<device::GamepadDataFetcher> CreateGamepadPlatformDataFetcher() { |
| 32 return std::unique_ptr<device::GamepadDataFetcher>( | 28 return std::unique_ptr<device::GamepadDataFetcher>( |
| 33 new device::GamepadPlatformDataFetcherLinux()); | 29 new device::GamepadPlatformDataFetcherLinux()); |
| 34 } | 30 } |
| 35 | 31 |
| 36 // Time between gamepad polls in milliseconds. | 32 // Time between gamepad polls in milliseconds. |
| 37 constexpr unsigned kPollingTimeIntervalMs = 16; | 33 constexpr unsigned kPollingTimeIntervalMs = 16; |
| 38 | 34 |
| 39 } // namespace | 35 } // namespace |
| 40 | 36 |
| 41 //////////////////////////////////////////////////////////////////////////////// | 37 //////////////////////////////////////////////////////////////////////////////// |
| 42 // GamingSeat::ThreadSafeGamepadChangeFetcher | 38 // GamingSeatJoydev::ThreadSafeGamepadChangeFetcher |
| 43 | 39 |
| 44 // Implements all methods and resources running on the polling thread. | 40 // Implements all methods and resources running on the polling thread. |
| 45 // This class is reference counted to allow it to shut down safely on the | 41 // This class is reference counted to allow it to shut down safely on the |
| 46 // polling thread even if the Gamepad has been destroyed on the origin thread. | 42 // polling thread even if the Gamepad has been destroyed on the origin thread. |
| 47 class GamingSeat::ThreadSafeGamepadChangeFetcher | 43 class GamingSeatJoydev::ThreadSafeGamepadChangeFetcher |
| 48 : public device::GamepadPadStateProvider, | 44 : public device::GamepadPadStateProvider, |
| 49 public base::RefCountedThreadSafe< | 45 public base::RefCountedThreadSafe< |
| 50 GamingSeat::ThreadSafeGamepadChangeFetcher> { | 46 GamingSeatJoydev::ThreadSafeGamepadChangeFetcher> { |
| 51 public: | 47 public: |
| 52 using ProcessGamepadChangesCallback = | 48 using ProcessGamepadChangesCallback = |
| 53 base::Callback<void(int index, const device::Gamepad)>; | 49 base::Callback<void(int index, const device::Gamepad)>; |
| 54 | 50 |
| 55 ThreadSafeGamepadChangeFetcher( | 51 ThreadSafeGamepadChangeFetcher( |
| 56 const ProcessGamepadChangesCallback& post_gamepad_changes, | 52 const ProcessGamepadChangesCallback& post_gamepad_changes, |
| 57 const CreateGamepadDataFetcherCallback& create_fetcher_callback, | 53 const CreateGamepadDataFetcherCallback& create_fetcher_callback, |
| 58 base::SingleThreadTaskRunner* task_runner) | 54 base::SingleThreadTaskRunner* task_runner) |
| 59 : process_gamepad_changes_(post_gamepad_changes), | 55 : process_gamepad_changes_(post_gamepad_changes), |
| 60 create_fetcher_callback_(create_fetcher_callback), | 56 create_fetcher_callback_(create_fetcher_callback), |
| 61 polling_task_runner_(task_runner), | 57 polling_task_runner_(task_runner), |
| 62 origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) { | 58 origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) { |
| 63 thread_checker_.DetachFromThread(); | 59 DETACH_FROM_THREAD(thread_checker_); |
| 64 } | 60 } |
| 65 | 61 |
| 66 // Enable or disable gamepad polling. Can be called from any thread. | 62 // Enable or disable gamepad polling. Can be called from any thread. |
| 67 void EnablePolling(bool enabled) { | 63 void EnablePolling(bool enabled) { |
| 68 polling_task_runner_->PostTask( | 64 polling_task_runner_->PostTask( |
| 69 FROM_HERE, | 65 FROM_HERE, |
| 70 base::Bind( | 66 base::Bind( |
| 71 &ThreadSafeGamepadChangeFetcher::EnablePollingOnPollingThread, | 67 &ThreadSafeGamepadChangeFetcher::EnablePollingOnPollingThread, |
| 72 make_scoped_refptr(this), enabled)); | 68 make_scoped_refptr(this), enabled)); |
| 73 } | 69 } |
| 74 | 70 |
| 75 private: | 71 private: |
| 76 friend class base::RefCountedThreadSafe<ThreadSafeGamepadChangeFetcher>; | 72 friend class base::RefCountedThreadSafe<ThreadSafeGamepadChangeFetcher>; |
| 77 | 73 |
| 78 ~ThreadSafeGamepadChangeFetcher() override {} | 74 ~ThreadSafeGamepadChangeFetcher() override {} |
| 79 | 75 |
| 80 // Enables or disables polling. | 76 // Enables or disables polling. |
| 81 void EnablePollingOnPollingThread(bool enabled) { | 77 void EnablePollingOnPollingThread(bool enabled) { |
| 82 DCHECK(thread_checker_.CalledOnValidThread()); | 78 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| 83 is_enabled_ = enabled; | 79 is_enabled_ = enabled; |
| 84 | 80 |
| 85 if (is_enabled_) { | 81 if (is_enabled_) { |
| 86 if (!fetcher_) { | 82 if (!fetcher_) { |
| 87 fetcher_ = create_fetcher_callback_.Run(); | 83 fetcher_ = create_fetcher_callback_.Run(); |
| 88 InitializeDataFetcher(fetcher_.get()); | 84 InitializeDataFetcher(fetcher_.get()); |
| 89 DCHECK(fetcher_); | 85 DCHECK(fetcher_); |
| 90 } | 86 } |
| 91 SchedulePollOnPollingThread(); | 87 SchedulePollOnPollingThread(); |
| 92 } else { | 88 } else { |
| 93 fetcher_.reset(); | 89 fetcher_.reset(); |
| 94 } | 90 } |
| 95 } | 91 } |
| 96 | 92 |
| 97 // Schedules the next poll on the polling thread. | 93 // Schedules the next poll on the polling thread. |
| 98 void SchedulePollOnPollingThread() { | 94 void SchedulePollOnPollingThread() { |
| 99 DCHECK(thread_checker_.CalledOnValidThread()); | 95 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| 100 DCHECK(fetcher_); | 96 DCHECK(fetcher_); |
| 101 | 97 |
| 102 if (!is_enabled_ || has_poll_scheduled_) | 98 if (!is_enabled_ || has_poll_scheduled_) |
| 103 return; | 99 return; |
| 104 | 100 |
| 105 has_poll_scheduled_ = true; | 101 has_poll_scheduled_ = true; |
| 106 polling_task_runner_->PostDelayedTask( | 102 polling_task_runner_->PostDelayedTask( |
| 107 FROM_HERE, | 103 FROM_HERE, |
| 108 base::Bind(&ThreadSafeGamepadChangeFetcher::PollOnPollingThread, | 104 base::Bind(&ThreadSafeGamepadChangeFetcher::PollOnPollingThread, |
| 109 make_scoped_refptr(this)), | 105 make_scoped_refptr(this)), |
| 110 base::TimeDelta::FromMilliseconds(kPollingTimeIntervalMs)); | 106 base::TimeDelta::FromMilliseconds(kPollingTimeIntervalMs)); |
| 111 } | 107 } |
| 112 | 108 |
| 113 // Polls devices for new data and posts gamepad changes back to origin thread. | 109 // Polls devices for new data and posts gamepad changes back to origin thread. |
| 114 void PollOnPollingThread() { | 110 void PollOnPollingThread() { |
| 115 DCHECK(thread_checker_.CalledOnValidThread()); | 111 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| 116 | 112 |
| 117 has_poll_scheduled_ = false; | 113 has_poll_scheduled_ = false; |
| 118 if (!is_enabled_) | 114 if (!is_enabled_) |
| 119 return; | 115 return; |
| 120 | 116 |
| 121 DCHECK(fetcher_); | 117 DCHECK(fetcher_); |
| 122 | 118 |
| 123 device::Gamepads new_state = state_; | 119 device::Gamepads new_state = state_; |
| 124 fetcher_->GetGamepadData( | 120 fetcher_->GetGamepadData( |
| 125 false /* No hardware changed notification from the system */); | 121 false /* No hardware changed notification from the system */); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 // The current state of all gamepads. | 169 // The current state of all gamepads. |
| 174 device::Gamepads state_; | 170 device::Gamepads state_; |
| 175 | 171 |
| 176 // True if a poll has been scheduled. | 172 // True if a poll has been scheduled. |
| 177 bool has_poll_scheduled_ = false; | 173 bool has_poll_scheduled_ = false; |
| 178 | 174 |
| 179 // True if the polling thread is paused. | 175 // True if the polling thread is paused. |
| 180 bool is_enabled_ = false; | 176 bool is_enabled_ = false; |
| 181 | 177 |
| 182 // ThreadChecker for the polling thread. | 178 // ThreadChecker for the polling thread. |
| 183 base::ThreadChecker thread_checker_; | 179 THREAD_CHECKER(thread_checker_); |
| 184 | 180 |
| 185 DISALLOW_COPY_AND_ASSIGN(ThreadSafeGamepadChangeFetcher); | 181 DISALLOW_COPY_AND_ASSIGN(ThreadSafeGamepadChangeFetcher); |
| 186 }; | 182 }; |
| 187 | 183 |
| 188 //////////////////////////////////////////////////////////////////////////////// | 184 //////////////////////////////////////////////////////////////////////////////// |
| 189 // GamingSeat, public: | 185 // GamingSeatJoydev, public: |
| 190 | 186 |
| 191 GamingSeat::GamingSeat(GamingSeatDelegate* gaming_seat_delegate, | 187 GamingSeatJoydev::GamingSeatJoydev( |
| 192 base::SingleThreadTaskRunner* polling_task_runner) | 188 GamingSeatDelegate* gaming_seat_delegate, |
| 193 : GamingSeat(gaming_seat_delegate, | 189 base::SingleThreadTaskRunner* polling_task_runner) |
| 194 polling_task_runner, | 190 : GamingSeatJoydev(gaming_seat_delegate, |
| 195 base::Bind(CreateGamepadPlatformDataFetcher)) {} | 191 polling_task_runner, |
| 192 base::Bind(CreateGamepadPlatformDataFetcher)) {} |
| 196 | 193 |
| 197 GamingSeat::GamingSeat(GamingSeatDelegate* gaming_seat_delegate, | 194 GamingSeatJoydev::GamingSeatJoydev( |
| 198 base::SingleThreadTaskRunner* polling_task_runner, | 195 GamingSeatDelegate* gaming_seat_delegate, |
| 199 CreateGamepadDataFetcherCallback create_fetcher_callback) | 196 base::SingleThreadTaskRunner* polling_task_runner, |
| 197 CreateGamepadDataFetcherCallback create_fetcher_callback) |
| 200 : delegate_(gaming_seat_delegate), | 198 : delegate_(gaming_seat_delegate), |
| 201 gamepad_delegates_{nullptr}, | 199 gamepad_delegates_{nullptr}, |
| 202 weak_ptr_factory_(this) { | 200 weak_ptr_factory_(this) { |
| 203 gamepad_change_fetcher_ = new ThreadSafeGamepadChangeFetcher( | 201 gamepad_change_fetcher_ = new ThreadSafeGamepadChangeFetcher( |
| 204 base::Bind(&GamingSeat::ProcessGamepadChanges, | 202 base::Bind(&GamingSeatJoydev::ProcessGamepadChanges, |
| 205 weak_ptr_factory_.GetWeakPtr()), | 203 weak_ptr_factory_.GetWeakPtr()), |
| 206 create_fetcher_callback, polling_task_runner); | 204 create_fetcher_callback, polling_task_runner); |
| 207 | 205 |
| 208 auto* helper = WMHelper::GetInstance(); | 206 auto* helper = WMHelper::GetInstance(); |
| 209 helper->AddFocusObserver(this); | 207 helper->AddFocusObserver(this); |
| 210 OnWindowFocused(helper->GetFocusedWindow(), nullptr); | 208 OnWindowFocused(helper->GetFocusedWindow(), nullptr); |
| 211 } | 209 } |
| 212 | 210 |
| 213 GamingSeat::~GamingSeat() { | 211 GamingSeatJoydev::~GamingSeatJoydev() { |
| 214 // Disable polling. Since ThreadSafeGamepadChangeFetcher are reference | 212 // Disable polling. Since ThreadSafeGamepadChangeFetcher are reference |
| 215 // counted, we can safely have it shut down after Gamepad has been destroyed. | 213 // counted, we can safely have it shut down after Gamepad has been destroyed. |
| 216 gamepad_change_fetcher_->EnablePolling(false); | 214 gamepad_change_fetcher_->EnablePolling(false); |
| 217 | 215 |
| 218 delegate_->OnGamingSeatDestroying(this); | 216 delegate_->OnGamingSeatDestroying(this); |
| 219 for (size_t i = 0; i < device::Gamepads::kItemsLengthCap; ++i) { | 217 for (size_t i = 0; i < device::Gamepads::kItemsLengthCap; ++i) { |
| 220 if (gamepad_delegates_[i]) { | 218 if (gamepad_delegates_[i]) { |
| 221 gamepad_delegates_[i]->OnRemoved(); | 219 gamepad_delegates_[i]->OnRemoved(); |
| 222 } | 220 } |
| 223 } | 221 } |
| 224 WMHelper::GetInstance()->RemoveFocusObserver(this); | 222 WMHelper::GetInstance()->RemoveFocusObserver(this); |
| 225 } | 223 } |
| 226 | 224 |
| 227 //////////////////////////////////////////////////////////////////////////////// | 225 //////////////////////////////////////////////////////////////////////////////// |
| 228 // aura::client::FocusChangeObserver overrides: | 226 // aura::client::FocusChangeObserver overrides: |
| 229 | 227 |
| 230 void GamingSeat::OnWindowFocused(aura::Window* gained_focus, | 228 void GamingSeatJoydev::OnWindowFocused(aura::Window* gained_focus, |
| 231 aura::Window* lost_focus) { | 229 aura::Window* lost_focus) { |
| 232 DCHECK(thread_checker_.CalledOnValidThread()); | 230 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| 233 Surface* target = nullptr; | 231 Surface* target = nullptr; |
| 234 if (gained_focus) { | 232 if (gained_focus) { |
| 235 target = Surface::AsSurface(gained_focus); | 233 target = Surface::AsSurface(gained_focus); |
| 236 if (!target) { | 234 if (!target) { |
| 237 aura::Window* top_level_window = gained_focus->GetToplevelWindow(); | 235 aura::Window* top_level_window = gained_focus->GetToplevelWindow(); |
| 238 if (top_level_window) | 236 if (top_level_window) |
| 239 target = ShellSurface::GetMainSurface(top_level_window); | 237 target = ShellSurface::GetMainSurface(top_level_window); |
| 240 } | 238 } |
| 241 } | 239 } |
| 242 | 240 |
| 243 bool focused = target && delegate_->CanAcceptGamepadEventsForSurface(target); | 241 bool focused = target && delegate_->CanAcceptGamepadEventsForSurface(target); |
| 244 | 242 |
| 245 gamepad_change_fetcher_->EnablePolling(focused); | 243 gamepad_change_fetcher_->EnablePolling(focused); |
| 246 } | 244 } |
| 247 | 245 |
| 248 //////////////////////////////////////////////////////////////////////////////// | 246 //////////////////////////////////////////////////////////////////////////////// |
| 249 // GamingSeat, private: | 247 // GamingSeatJoydev, private: |
| 250 | 248 |
| 251 void GamingSeat::ProcessGamepadChanges(int index, | 249 void GamingSeatJoydev::ProcessGamepadChanges(int index, |
| 252 const device::Gamepad new_pad) { | 250 const device::Gamepad new_pad) { |
| 253 DCHECK(thread_checker_.CalledOnValidThread()); | 251 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| 254 bool send_frame = false; | 252 bool send_frame = false; |
| 255 | 253 |
| 256 device::Gamepad& pad_state = pad_state_.items[index]; | 254 device::Gamepad& pad_state = pad_state_.items[index]; |
| 257 // Update connection state. | 255 // Update connection state. |
| 258 GamepadDelegate* delegate = gamepad_delegates_[index]; | 256 GamepadDelegate* delegate = gamepad_delegates_[index]; |
| 259 if (new_pad.connected != pad_state.connected) { | 257 if (new_pad.connected != pad_state.connected) { |
| 260 // New pad is disconnected. | 258 // New pad is disconnected. |
| 261 if (!new_pad.connected) { | 259 if (!new_pad.connected) { |
| 262 // If gamepad is disconnected now, it should be connected before, then | 260 // If gamepad is disconnected now, it should be connected before, then |
| 263 // gamepad_delegate should not be null. | 261 // gamepad_delegate should not be null. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 delegate->OnButton(button_id, new_button.pressed, new_button.value); | 297 delegate->OnButton(button_id, new_button.pressed, new_button.value); |
| 300 } | 298 } |
| 301 } | 299 } |
| 302 if (send_frame) | 300 if (send_frame) |
| 303 delegate->OnFrame(); | 301 delegate->OnFrame(); |
| 304 | 302 |
| 305 pad_state = new_pad; | 303 pad_state = new_pad; |
| 306 } | 304 } |
| 307 | 305 |
| 308 } // namespace exo | 306 } // namespace exo |
| OLD | NEW |