| // 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. |
| |
| #ifndef COMPONENTS_EXO_SEAT_H_ |
| #define COMPONENTS_EXO_SEAT_H_ |
| |
| #include <array> |
| |
| #include "base/callback.h" |
| #include "base/check.h" |
| #include "base/containers/flat_map.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/observer_list.h" |
| #include "build/chromeos_buildflags.h" |
| #include "components/exo/data_source_observer.h" |
| #include "components/exo/key_state.h" |
| #include "ui/aura/client/drag_drop_delegate.h" |
| #include "ui/aura/client/focus_change_observer.h" |
| #include "ui/base/clipboard/clipboard_observer.h" |
| #include "ui/base/clipboard/scoped_clipboard_writer.h" |
| #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-forward.h" |
| #include "ui/events/event_handler.h" |
| #include "ui/events/keycodes/dom/dom_codes.h" |
| #include "ui/events/platform/platform_event_observer.h" |
| |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| #include "ash/ime/ime_controller_impl.h" |
| #include "components/exo/ui_lock_controller.h" |
| #endif |
| |
| namespace ui { |
| enum class DomCode; |
| class KeyEvent; |
| } // namespace ui |
| |
| namespace exo { |
| class DragDropOperation; |
| class DataExchangeDelegate; |
| class Pointer; |
| class ScopedDataSource; |
| class SeatObserver; |
| class Surface; |
| class XkbTracker; |
| |
| // Seat object represent a group of input devices such as keyboard, pointer and |
| // touch devices and keeps track of input focus. |
| class Seat : public aura::client::FocusChangeObserver, |
| public ui::PlatformEventObserver, |
| public ui::EventHandler, |
| public ui::ClipboardObserver, |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| public ash::ImeControllerImpl::Observer, |
| #endif |
| public DataSourceObserver { |
| public: |
| explicit Seat(std::unique_ptr<DataExchangeDelegate> delegate); |
| Seat(); |
| Seat(const Seat&) = delete; |
| Seat& operator=(const Seat&) = delete; |
| ~Seat() override; |
| |
| using FocusChangedCallback = |
| base::RepeatingCallback<void(Surface*, Surface*, bool)>; |
| |
| void Shutdown(); |
| |
| // Registers the observer with the given priority. |
| // Observers with smaller priority value will be called earlier. |
| // The same observer should not be registered twice or more even with |
| // different priorities. If the order of observer invocations with |
| // the same priority is implementation dependent. |
| // The priority must be in a range of |
| // [0, kMaxObserverPriority] inclusive. |
| void AddObserver(SeatObserver* observer, int priority); |
| |
| // Unregisters the observer. |
| void RemoveObserver(SeatObserver* observer); |
| |
| // Returns true if the given priority can be used for AddObserver. |
| static constexpr bool IsValidObserverPriority(int priority) { |
| return 0 <= priority && priority <= kMaxObserverPriority; |
| } |
| |
| // Notify observers about pointer capture state changes. |
| void NotifyPointerCaptureEnabled(Pointer* pointer, |
| aura::Window* capture_window); |
| void NotifyPointerCaptureDisabled(Pointer* pointer, |
| aura::Window* capture_window); |
| |
| // Returns currently focused surface. This is virtual so that we can override |
| // the behavior for testing. |
| virtual Surface* GetFocusedSurface(); |
| |
| // Returns currently pressed keys. |
| const base::flat_map<ui::DomCode, KeyState>& pressed_keys() const { |
| return pressed_keys_; |
| } |
| |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| const XkbTracker* xkb_tracker() const { return xkb_tracker_.get(); } |
| #endif |
| |
| DataExchangeDelegate* data_exchange_delegate() { |
| return data_exchange_delegate_.get(); |
| } |
| |
| // Returns physical code for the currently processing event. |
| ui::DomCode physical_code_for_currently_processing_event() const { |
| return physical_code_for_currently_processing_event_; |
| } |
| |
| // Sets clipboard data from |source|. |
| void SetSelection(DataSource* source); |
| |
| void StartDrag(DataSource* source, |
| Surface* origin, |
| Surface* icon, |
| ui::mojom::DragEventSource event_source); |
| |
| // Sets the last location in screen coordinates, irrespective of mouse or |
| // touch. |
| void SetLastPointerLocation(const gfx::PointF& last_pointer_location); |
| |
| // Abort any drag operations that haven't been started yet. |
| void AbortPendingDragOperation(); |
| |
| // Overridden from aura::client::FocusChangeObserver: |
| void OnWindowFocused(aura::Window* gained_focus, |
| aura::Window* lost_focus) override; |
| |
| // Overridden from ui::PlatformEventObserver: |
| void WillProcessEvent(const ui::PlatformEvent& event) override; |
| void DidProcessEvent(const ui::PlatformEvent& event) override; |
| |
| // Overridden from ui::EventHandler: |
| void OnKeyEvent(ui::KeyEvent* event) override; |
| |
| // Overridden from ui::ClipboardObserver: |
| void OnClipboardDataChanged() override; |
| |
| // Overridden from DataSourceObserver: |
| void OnDataSourceDestroying(DataSource* source) override; |
| |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| // Overridden from ash::ImeControllerImpl::Observer: |
| void OnCapsLockChanged(bool enabled) override; |
| void OnKeyboardLayoutNameChanged(const std::string& layout_name) override; |
| |
| UILockController* GetUILockControllerForTesting(); |
| #endif |
| |
| void set_physical_code_for_currently_processing_event_for_testing( |
| ui::DomCode physical_code_for_currently_processing_event) { |
| physical_code_for_currently_processing_event_ = |
| physical_code_for_currently_processing_event; |
| } |
| |
| base::WeakPtr<DragDropOperation> get_drag_drop_operation_for_testing() { |
| return drag_drop_operation_; |
| } |
| |
| bool was_shutdown() const { return was_shutdown_; } |
| |
| private: |
| class RefCountedScopedClipboardWriter; |
| |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| // Called when the focused window is a Lacros window and a source |
| // DataTransferEndpoint is read in the available MIME types. This |
| // is currently used to synchronize clipboard source metadata from |
| // Lacros to Ash. |
| void OnDataTransferEndpointRead( |
| scoped_refptr<RefCountedScopedClipboardWriter> writer, |
| base::OnceClosure callback, |
| const std::string& mime_type, |
| std::u16string data); |
| #endif |
| |
| // Called when data is read from FD passed from a client. |
| // |data| is read data. |source| is source of the data, or nullptr if |
| // DataSource has already been destroyed. |
| void OnTextRead(scoped_refptr<RefCountedScopedClipboardWriter> writer, |
| base::OnceClosure callback, |
| const std::string& mime_type, |
| std::u16string data); |
| void OnRTFRead(scoped_refptr<RefCountedScopedClipboardWriter> writer, |
| base::OnceClosure callback, |
| const std::string& mime_type, |
| const std::vector<uint8_t>& data); |
| void OnHTMLRead(scoped_refptr<RefCountedScopedClipboardWriter> writer, |
| base::OnceClosure callback, |
| const std::string& mime_type, |
| std::u16string data); |
| void OnImageRead(scoped_refptr<RefCountedScopedClipboardWriter> writer, |
| base::OnceClosure callback, |
| const std::string& mime_type, |
| const std::vector<uint8_t>& data); |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| void OnImageDecoded(base::OnceClosure callback, |
| scoped_refptr<RefCountedScopedClipboardWriter> writer, |
| const SkBitmap& bitmap); |
| #endif // BUILDFLAG(IS_CHROMEOS_ASH) |
| void OnFilenamesRead(ui::EndpointType source, |
| scoped_refptr<RefCountedScopedClipboardWriter> writer, |
| base::OnceClosure callback, |
| const std::string& mime_type, |
| const std::vector<uint8_t>& data); |
| void OnWebCustomDataRead( |
| scoped_refptr<RefCountedScopedClipboardWriter> writer, |
| base::OnceClosure callback, |
| const std::string& mime_type, |
| const std::vector<uint8_t>& data); |
| |
| void OnAllReadsFinished( |
| scoped_refptr<RefCountedScopedClipboardWriter> writer); |
| |
| // Max value of SeatObserver's priority. Both side are inclusive. |
| static constexpr int kMaxObserverPriority = 1; |
| |
| // Map from priority to a list of SeatOberver pointers. |
| std::array<base::ObserverList<SeatObserver>::Unchecked, |
| kMaxObserverPriority + 1> |
| priority_observer_list_; |
| |
| // The platform code is the key in this map as it represents the physical |
| // key that was pressed. The value is a potentially rewritten code that the |
| // physical key press generated. |
| base::flat_map<ui::DomCode, KeyState> pressed_keys_; |
| ui::DomCode physical_code_for_currently_processing_event_ = ui::DomCode::NONE; |
| |
| // Data source being used as a clipboard content. |
| std::unique_ptr<ScopedDataSource> selection_source_; |
| |
| base::WeakPtr<DragDropOperation> drag_drop_operation_; |
| |
| // True while Seat is updating clipboard data to selection source. |
| bool changing_clipboard_data_to_selection_source_; |
| |
| gfx::PointF last_pointer_location_; |
| |
| bool was_shutdown_ = false; |
| |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| std::unique_ptr<UILockController> ui_lock_controller_; |
| std::unique_ptr<XkbTracker> xkb_tracker_; |
| #endif // BUILDFLAG(IS_CHROMEOS_ASH) |
| |
| std::unique_ptr<DataExchangeDelegate> data_exchange_delegate_; |
| base::WeakPtrFactory<Seat> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace exo |
| |
| #endif // COMPONENTS_EXO_SEAT_H_ |