// 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/gaming_seat.h" #include "components/exo/gamepad_delegate.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) : delegate_(delegate) { auto* helper = WMHelper::GetInstance(); helper->AddFocusObserver(this); OnWindowFocused(helper->GetFocusedWindow(), nullptr); } GamingSeat::~GamingSeat() { if (focused_) ui::GamepadProviderOzone::GetInstance()->RemoveGamepadObserver(this); delegate_->OnGamingSeatDestroying(this); // Disconnect all the gamepads. for (auto& entry : gamepads_) entry.second->OnRemoved(); WMHelper::GetInstance()->RemoveFocusObserver(this); } //////////////////////////////////////////////////////////////////////////////// // ui::aura::client::FocusChangeObserver 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_ != focused) { focused_ = focused; if (focused) { ui::GamepadProviderOzone::GetInstance()->AddGamepadObserver(this); OnGamepadDevicesUpdated(); } else { ui::GamepadProviderOzone::GetInstance()->RemoveGamepadObserver(this); } } } //////////////////////////////////////////////////////////////////////////////// // ui::GamepadObserver overrides: void GamingSeat::OnGamepadDevicesUpdated() { std::vector gamepad_devices = ui::GamepadProviderOzone::GetInstance()->GetGamepadDevices(); base::flat_map 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