| // Copyright 2015 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef COMPONENTS_EXO_KEYBOARD_H_ |
| #define COMPONENTS_EXO_KEYBOARD_H_ |
| |
| #include <memory> |
| |
| #include "ash/ime/ime_controller_impl.h" |
| #include "ash/public/cpp/keyboard/keyboard_controller_observer.h" |
| #include "ash/public/mojom/input_device_settings.mojom.h" |
| #include "base/containers/flat_map.h" |
| #include "base/containers/flat_set.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/observer_list.h" |
| #include "base/time/time.h" |
| #include "components/exo/key_state.h" |
| #include "components/exo/keyboard_observer.h" |
| #include "components/exo/seat_observer.h" |
| #include "components/exo/surface_observer.h" |
| #include "ui/events/event.h" |
| #include "ui/events/event_handler.h" |
| |
| namespace ui { |
| enum class DomCode : uint32_t; |
| class KeyEvent; |
| } |
| |
| namespace exo { |
| class KeyboardDelegate; |
| class KeyboardDeviceConfigurationDelegate; |
| class Seat; |
| class Surface; |
| |
| // This class implements a client keyboard that represents one or more keyboard |
| // devices. |
| class Keyboard : public ui::EventHandler, |
| public SurfaceObserver, |
| public SeatObserver, |
| public ash::KeyboardControllerObserver, |
| public ash::ImeControllerImpl::Observer { |
| public: |
| Keyboard(std::unique_ptr<KeyboardDelegate> delegate, Seat* seat); |
| Keyboard(const Keyboard&) = delete; |
| Keyboard& operator=(const Keyboard&) = delete; |
| ~Keyboard() override; |
| |
| KeyboardDelegate* delegate() const { return delegate_.get(); } |
| |
| bool HasDeviceConfigurationDelegate() const; |
| void SetDeviceConfigurationDelegate( |
| KeyboardDeviceConfigurationDelegate* delegate); |
| |
| // Management of the observer list. |
| void AddObserver(KeyboardObserver* observer); |
| bool HasObserver(KeyboardObserver* observer) const; |
| void RemoveObserver(KeyboardObserver* observer); |
| |
| void SetNeedKeyboardKeyAcks(bool need_acks); |
| bool AreKeyboardKeyAcksNeeded() const; |
| |
| void AckKeyboardKey(uint32_t serial, bool handled); |
| |
| // Overridden from ui::EventHandler: |
| void OnKeyEvent(ui::KeyEvent* event) override; |
| |
| // Overridden from SurfaceObserver: |
| void OnSurfaceDestroying(Surface* surface) override; |
| |
| // Overridden from SeatObserver: |
| void OnSurfaceFocused(Surface* gained_focus, |
| Surface* lost_focus, |
| bool has_focused_surface) override; |
| void OnKeyboardModifierUpdated() override; |
| |
| // Overridden from ash::KeyboardControllerObserver: |
| void OnKeyboardEnableFlagsChanged( |
| const std::set<keyboard::KeyboardEnableFlag>& flags) override; |
| void OnKeyRepeatSettingsChanged( |
| const ash::KeyRepeatSettings& settings) override; |
| |
| // Overridden from ash::ImeControllerImpl::Observer: |
| void OnCapsLockChanged(bool enabled) override; |
| void OnKeyboardLayoutNameChanged(const std::string& layout_name) override; |
| |
| Surface* focused_surface_for_testing() const { return focus_; } |
| |
| private: |
| // Returns a set of keys with keys that should not be handled by the surface |
| // filtered out from pressed_keys_. |
| base::flat_map<PhysicalCode, base::flat_set<KeyState>> |
| GetPressedKeysForSurface(Surface* surface); |
| |
| // Change keyboard focus to |surface|. |
| void SetFocus(Surface* surface); |
| |
| // Processes expired key state changes in |pending_key_acks_| as they have not |
| // been acknowledged. |
| void ProcessExpiredPendingKeyAcks(); |
| |
| // Schedule next call of ProcessExpiredPendingKeyAcks after |delay| |
| void ScheduleProcessExpiredPendingKeyAcks(base::TimeDelta delay); |
| |
| // Adds/Removes pre or post event handler depending on if key acks are needed. |
| // If key acks are needed, pre target handler will be added because this class |
| // wants to dispatch keys before they are consumed by Chrome. Otherwise, post |
| // target handler will be added because all accelerators should be handled by |
| // Chrome before they are dispatched by this class. |
| void AddEventHandler(); |
| void RemoveEventHandler(); |
| |
| // Notify the current keyboard type. |
| void UpdateKeyboardType(); |
| |
| // The delegate instance that all events except for events about device |
| // configuration are dispatched to. |
| std::unique_ptr<KeyboardDelegate> delegate_; |
| |
| // Seat that the Keyboard recieves focus events from. |
| const raw_ptr<Seat> seat_; |
| |
| // The delegate instance that events about device configuration are dispatched |
| // to. |
| raw_ptr<KeyboardDeviceConfigurationDelegate> device_configuration_delegate_ = |
| nullptr; |
| |
| // Indicates that each key event is expected to be acknowledged. |
| bool are_keyboard_key_acks_needed_ = false; |
| |
| // The current focus surface for the keyboard. |
| raw_ptr<Surface> focus_ = nullptr; |
| |
| // Set of currently pressed keys. First value is a platform code and second |
| // value is the code that was delivered to client. See Seat.h for more |
| // details. |
| base::flat_map<PhysicalCode, base::flat_set<KeyState>> pressed_keys_; |
| |
| // Key state changes that are expected to be acknowledged. |
| using KeyStateChange = std::pair<ui::KeyEvent, base::TimeTicks>; |
| base::flat_map<uint32_t, KeyStateChange> pending_key_acks_; |
| |
| // Indicates that a ProcessExpiredPendingKeyAcks call is pending. |
| bool process_expired_pending_key_acks_pending_ = false; |
| |
| // Delay until a key state change expected to be acknowledged is expired. |
| const base::TimeDelta expiration_delay_for_pending_key_acks_; |
| |
| // Tracks whether the last key event is the target of autorepeat. |
| bool auto_repeat_enabled_ = true; |
| |
| // True when the ARC app window is focused. |
| // TODO(yhanada, https://crbug.com/847500): Remove this when we find a way to |
| // fix https://crbug.com/847500 without breaking ARC++ apps. |
| bool focused_on_ime_supported_surface_ = false; |
| |
| base::ObserverList<KeyboardObserver>::Unchecked observer_list_; |
| |
| base::WeakPtrFactory<Keyboard> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace exo |
| |
| #endif // COMPONENTS_EXO_KEYBOARD_H_ |