1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
|
// 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_CAMERA_PREVIEW_VIEW_H_
#define ASH_CAPTURE_MODE_CAPTURE_MODE_CAMERA_PREVIEW_VIEW_H_
#include "ash/accessibility/accessibility_controller.h"
#include "ash/accessibility/accessibility_observer.h"
#include "ash/capture_mode/camera_video_frame_renderer.h"
#include "ash/capture_mode/capture_mode_camera_controller.h"
#include "ash/capture_mode/capture_mode_session_focus_cycler.h"
#include "ash/style/icon_button.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/gfx/geometry/size.h"
#include "ui/views/view.h"
namespace media {
struct VideoCaptureFormat;
} // namespace media
namespace video_capture::mojom {
class VideoSource;
} // namespace video_capture::mojom
namespace views {
class NativeViewHost;
} // namespace views
namespace ash {
class CaptureModeCameraController;
class ScopedA11yOverrideWindowSetter;
// Resize button inside the camera preview view.
class CameraPreviewResizeButton
: public IconButton,
public CaptureModeSessionFocusCycler::HighlightableView {
METADATA_HEADER(CameraPreviewResizeButton, IconButton)
public:
CameraPreviewResizeButton(CameraPreviewView* camera_preview_view,
views::Button::PressedCallback callback,
const gfx::VectorIcon& icon);
CameraPreviewResizeButton(const CameraPreviewResizeButton&) = delete;
CameraPreviewResizeButton& operator=(const CameraPreviewResizeButton&) =
delete;
~CameraPreviewResizeButton() override;
// CaptureModeSessionFocusCycler::HighlightableView:
views::View* GetView() override;
void PseudoFocus() override;
void PseudoBlur() override;
private:
const raw_ptr<CameraPreviewView> camera_preview_view_; // not owned.
};
// A view that acts as the contents view of the camera preview widget. It will
// be responsible for painting the latest camera video frame inside its bounds.
class CameraPreviewView
: public views::View,
public CaptureModeSessionFocusCycler::HighlightableView,
public AccessibilityObserver {
METADATA_HEADER(CameraPreviewView, views::View)
public:
CameraPreviewView(
CaptureModeCameraController* camera_controller,
const CameraId& camera_id,
mojo::Remote<video_capture::mojom::VideoSource> camera_video_source,
const media::VideoCaptureFormat& capture_format,
bool should_flip_frames_horizontally);
CameraPreviewView(const CameraPreviewView&) = delete;
CameraPreviewView& operator=(const CameraPreviewView&) = delete;
~CameraPreviewView() override;
const CameraId& camera_id() const { return camera_id_; }
CameraPreviewResizeButton* resize_button() const { return resize_button_; }
bool is_collapsible() const { return is_collapsible_; }
bool should_flip_frames_horizontally() const {
return camera_video_renderer_.should_flip_frames_horizontally();
}
// Initializes this view to start showing the camera video frames from the
// associated camera device. Note that this should only be called after this
// view has been added to a widget (see `AddedToWidget()` below).
void Initialize();
// Sets this camera preview collapsability to the given `value`, which will
// update the resize button visibility.
void SetIsCollapsible(bool value);
// Returns true if the `event` has been handled by CameraPrevieView. It
// happens if it is control+arrow keys, which will be used to move the camera
// preview to different snap positions.
bool MaybeHandleKeyEvent(const ui::KeyEvent* event);
// Called to update visibility of the `resize_button_` when necessary.
void RefreshResizeButtonVisibility();
// Updates the a11y override window when focus state changes on the camera
// preview. The a11y override window will be set to nullptr if neither the
// camera preview nor the resize button has focus. This is done to make sure
// a11y focus can be moved to others appropriately.
void UpdateA11yOverrideWindow();
// Removes the focus from camera preview when necessary. Happens if mouse
// pressing outside of the camera preview when it has focus. A11y override
// window will be updated as well.
void MaybeBlurFocus(const ui::MouseEvent& event);
// views::View:
void AddedToWidget() override;
bool OnMousePressed(const ui::MouseEvent& event) override;
bool OnMouseDragged(const ui::MouseEvent& event) override;
void OnMouseReleased(const ui::MouseEvent& event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
void OnMouseEntered(const ui::MouseEvent& event) override;
void OnMouseExited(const ui::MouseEvent& event) override;
void Layout(PassKey) override;
// CaptureModeSessionFocusCycler::HighlightableView:
views::View* GetView() override;
std::unique_ptr<views::HighlightPathGenerator> CreatePathGenerator() override;
// AccessibilityObserver:
void OnAccessibilityStatusChanged() override;
void OnAccessibilityControllerShutdown() override;
base::OneShotTimer* resize_button_hide_timer_for_test() {
return &resize_button_hide_timer_;
}
private:
friend class CameraPreviewResizeButton;
friend class CaptureModeTestApi;
// Called when the resize button is clicked or touched.
void OnResizeButtonPressed();
// Updates the icon of the `resize_button_` based on value of
// `is_camera_preview_collapsed()` inferred from the `camera_controller`.
void UpdateResizeButton();
// Updates the tooltip of the `resize_button_`. The `resize_button_` can be an
// expand button or collapse button.
void UpdateResizeButtonTooltip();
// Located events within the bounds of this view should be sent to, and
// handled by this view only (e.g. for drag and drop). They should not be sent
// to any native window hosting the camera video frames, otherwise we will
// lose those events. This function disable event targeting for the
// `camera_video_host_view_` and all the native windows it is hosting.
void DisableEventHandlingInCameraVideoHostHierarchy();
// Fades in or out the `resize_button_` and updates its visibility
// accordingly.
void FadeInResizeButton();
void FadeOutResizeButton();
// Called when the mouse exits the camera preview, after the latest tap inside
// the camera preview or when focus being removed from the resize button to
// start the `resize_button_hide_timer_`.
void ScheduleRefreshResizeButtonVisibility();
// Returns the target opacity for resize button.
float CalculateResizeButtonTargetOpacity();
// Removes the focus from the camera preview and updates the a11y override
// window.
void BlurA11yFocus();
const raw_ptr<CaptureModeCameraController> camera_controller_;
// The ID of the camera for which this preview was created.
const CameraId camera_id_;
// Renders the camera video frames into its `host_window()`.
CameraVideoFrameRenderer camera_video_renderer_;
// The view that hosts the native window `host_window()` of the
// `camera_video_renderer_` into this view's hierarchy.
const raw_ptr<views::NativeViewHost> camera_video_host_view_;
const raw_ptr<CameraPreviewResizeButton> resize_button_;
// Started when the mouse exits the camera preview or after the latest tap
// inside the camera preview. Runs RefreshResizeButtonVisibility() to fade out
// the resize button if possible.
base::OneShotTimer resize_button_hide_timer_;
// True if the size of the preview in the expanded state is big enough to
// allow it to be collapsible.
bool is_collapsible_ = true;
// True only while handling a gesture tap event on this view.
bool has_been_tapped_ = false;
base::ScopedObservation<AccessibilityController, AccessibilityObserver>
accessibility_observation_{this};
// Helps to update the current a11y override window. It will be the native
// window of the camera preview or nullptr, depends on whether the camera
// preview has focus or not. Accessibility features will focus on the window
// after it is set. Once `this` goes out of scope, the a11y override window is
// set to nullptr.
std::unique_ptr<ScopedA11yOverrideWindowSetter> scoped_a11y_overrider_;
base::WeakPtrFactory<CameraPreviewView> weak_ptr_factory_{this};
};
} // namespace ash
#endif // ASH_CAPTURE_MODE_CAPTURE_MODE_CAMERA_PREVIEW_VIEW_H_
|