| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef ASH_CAPTURE_MODE_CAPTURE_MODE_DEMO_TOOLS_CONTROLLER_H_ |
| #define ASH_CAPTURE_MODE_CAPTURE_MODE_DEMO_TOOLS_CONTROLLER_H_ |
| |
| #include "base/functional/callback_forward.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/timer/timer.h" |
| #include "ui/base/ime/input_method_observer.h" |
| #include "ui/base/ime/text_input_client.h" |
| #include "ui/events/keycodes/keyboard_codes_posix.h" |
| #include "ui/views/widget/unique_widget_ptr.h" |
| #include "ui/views/widget/widget.h" |
| |
| namespace ui { |
| class KeyEvent; |
| } // namespace ui |
| |
| namespace ash { |
| |
| class PointerHighlightLayer; |
| class KeyComboView; |
| class VideoRecordingWatcher; |
| |
| using MouseHighlightLayers = |
| std::vector<std::unique_ptr<PointerHighlightLayer>>; |
| |
| using TouchHighlightLayersMap = |
| base::flat_map<ui::PointerId, std::unique_ptr<PointerHighlightLayer>>; |
| |
| // Observes and decides whether to show clicks (or taps) highlights and a helper |
| // widget that represents the currently pressed key combination or not. The key |
| // combination will be used to construct or modify the `KeyComboViewer`. The |
| // `CaptureModeDemoToolsController` will only be available during video |
| // recording and has to be explicitly enabled by the user. |
| class CaptureModeDemoToolsController : public ui::InputMethodObserver { |
| public: |
| explicit CaptureModeDemoToolsController( |
| VideoRecordingWatcher* video_recording_watcher); |
| CaptureModeDemoToolsController(const CaptureModeDemoToolsController&) = |
| delete; |
| CaptureModeDemoToolsController& operator=( |
| const CaptureModeDemoToolsController&) = delete; |
| ~CaptureModeDemoToolsController() override; |
| |
| const views::Widget* key_combo_widget() const { |
| return key_combo_widget_.get(); |
| } |
| |
| // Decides whether to show a helper widget for the `event` or not. |
| void OnKeyEvent(ui::KeyEvent* event); |
| |
| // Creates a new highlight layer each time it gets called and performs the |
| // grow-and-fade-out animation on it. |
| void PerformMousePressAnimation(const gfx::PointF& event_location_in_window); |
| |
| // Refreshes the bounds of `key_combo_widget_`. |
| void RefreshBounds(); |
| |
| // Decides whether to show the highlight for the touch event or not. |
| void OnTouchEvent(ui::EventType event_type, |
| ui::PointerId pointer_id, |
| const gfx::PointF& event_location_in_window); |
| |
| // ui::InputMethodObserver: |
| void OnFocus() override {} |
| void OnBlur() override {} |
| void OnCaretBoundsChanged(const ui::TextInputClient* client) override {} |
| void OnTextInputStateChanged(const ui::TextInputClient* client) override; |
| void OnInputMethodDestroyed(const ui::InputMethod* input_method) override {} |
| |
| private: |
| friend class CaptureModeDemoToolsTestApi; |
| |
| void OnKeyUpEvent(ui::KeyEvent* event); |
| void OnKeyDownEvent(ui::KeyEvent* event); |
| |
| // Refreshes the state of the `key_combo_view_` based on the current state of |
| // `modifiers_` and `last_non_modifier_key_`. |
| void RefreshKeyComboViewer(); |
| |
| gfx::Rect CalculateKeyComboWidgetBounds() const; |
| |
| // Returns true if there is no modifier keys pressed and the non-modifier key |
| // can not be displayed independently. |
| bool ShouldResetKeyComboWidget() const; |
| |
| // Resets the `key_combo_widget_` when the `key_up_refresh_timer_` expires. |
| void AnimateToResetKeyComboWidget(); |
| |
| void UpdateTextInputType(const ui::TextInputClient* client); |
| |
| // Called when the mouse highlight animation ends to remove the corresponding |
| // pointer highlight from the `mouse_highlight_layers_`. |
| void OnMouseHighlightAnimationEnded( |
| PointerHighlightLayer* pointer_highlight_layer_ptr); |
| |
| // Creates a new highlight layer each time it gets called and performs the |
| // grow animation on it. |
| void OnTouchDown(const ui::PointerId& pointer_id, |
| const gfx::PointF& event_location_in_window); |
| |
| // Performs the grow-and-fade-out animation on an existing highlight layer |
| // that corresponds to the given `pointer_id`. |
| void OnTouchUp(const ui::PointerId& pointer_id, |
| const gfx::PointF& event_location_in_window); |
| |
| // Sets the bounds of the touch highlight layer that corresponds to the |
| // `pointer_id` based on the `event_location_in_window` of the touch event |
| // when it gets called on touch dragged. |
| void OnTouchDragged(const ui::PointerId& pointer_id, |
| const gfx::PointF& event_location_in_window); |
| |
| const raw_ptr<VideoRecordingWatcher, ExperimentalAsh> |
| video_recording_watcher_; |
| views::UniqueWidgetPtr key_combo_widget_; |
| raw_ptr<KeyComboView, ExperimentalAsh> key_combo_view_ = nullptr; |
| |
| // The state of the modifier keys i.e. Shift/Ctrl/Alt/Launcher keys. |
| int modifiers_ = 0; |
| |
| // The most recently pressed non-modifier key. |
| ui::KeyboardCode last_non_modifier_key_ = ui::VKEY_UNKNOWN; |
| |
| // True if the cursor and focus is currently in a text input |
| // field, false otherwise. |
| bool in_text_input_ = false; |
| |
| // Used to hold on `RefreshKeyComboViewer`. The key combo widget will be |
| // scheduled to hide after `capture_mode::kRefreshKeyComboWidgetLongDelay` |
| // when a key up event is received, and the remaining pressed keys are no |
| // longer displayable, e.g. for a key combo Ctrl |
| // + C, after Ctrl is released, the remaining C is no longer displayable on |
| // its own as a complete key combo, so the widget will be scheduled to hide |
| // after `capture_mode::kRefreshKeyComboWidgetLongDelay`. Otherwise |
| // `capture_mode::kRefreshKeyComboWidgetShortDelay` will be used as the |
| // threshold duration to decide the user intention on whether to do an update |
| // or release multiple keys at one time. |
| base::OneShotTimer key_up_refresh_timer_; |
| |
| // Contains all the mouse highlight layers that are being animated. |
| MouseHighlightLayers mouse_highlight_layers_; |
| |
| // Maps the PointerHighlightLayer of the touch event by the pointer id as the |
| // key. |
| TouchHighlightLayersMap touch_pointer_id_to_highlight_layer_map_; |
| |
| // If set, it will be called when the mouse highlight animation is completed. |
| base::OnceClosure on_mouse_highlight_animation_ended_callback_for_test_; |
| |
| base::WeakPtrFactory<CaptureModeDemoToolsController> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace ash |
| |
| #endif // ASH_CAPTURE_MODE_CAPTURE_MODE_DEMO_TOOLS_CONTROLLER_H_ |