// Copyright 2020 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_UTIL_H_
#define ASH_CAPTURE_MODE_CAPTURE_MODE_UTIL_H_
#include <optional>
#include <string>
#include "ash/ash_export.h"
#include "ash/capture_mode/capture_mode_types.h"
#include "base/time/time.h"
#include "ui/gfx/animation/tween.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/size.h"
#include "ui/views/highlight_border.h"
namespace aura {
class Window;
} // namespace aura
namespace chromeos {
class FrameHeader;
} // namespace chromeos
namespace gfx {
class PointF;
class Rect;
class Transform;
} // namespace gfx
namespace ui {
class ColorProvider;
class Layer;
class LocatedEvent;
} // namespace ui
namespace views {
class View;
class Widget;
class Label;
class BoxLayout;
} // namespace views
namespace ash {
class StopRecordingButtonTray;
namespace capture_mode_util {
// Returns true if the capture mode feature is enabled and capture mode is
// active. This method allows callers to avoid including the full header for
// CaptureModeController, which has many transitive includes.
ASH_EXPORT bool IsCaptureModeActive();
// Retrieves the screen location for the `event`.
gfx::PointF GetEventScreenLocation(const ui::LocatedEvent& event);
// Retrieves the point on the |rect| associated with |position|.
ASH_EXPORT gfx::Point GetLocationForFineTunePosition(const gfx::Rect& rect,
FineTunePosition position);
// Return whether |position| is a corner.
bool IsCornerFineTunePosition(FineTunePosition position);
// Returns the stop recording tray button on the given `root`. It may return
// `nullptr` during shutdown or if `root` is destroying.
StopRecordingButtonTray* GetStopRecordingButtonForRoot(aura::Window* root);
// Sets the visibility of the stop-recording button in the Shelf's status area
// widget of the given |root| window.
void SetStopRecordingButtonVisibility(aura::Window* root, bool visible);
// Triggers an accessibility alert to give the user feedback.
void TriggerAccessibilityAlert(const std::string& message);
void TriggerAccessibilityAlert(int message_id);
// Same as TriggerAccessibilityAlert above, but triggers the alert
// asynchronously as soon as possible. This is used to make sure consecutive
// alerts do not override one another, so all of them can be announced by
// ChromeVox.
void TriggerAccessibilityAlertSoon(const std::string& message);
void TriggerAccessibilityAlertSoon(int message_id);
// Adjusts the bounds if needed so that the `out_bounds` is always within the
// `confined_bounds`.
void AdjustBoundsWithinConfinedBounds(const gfx::Rect& confined_bounds,
gfx::Rect& out_bounds);
// Returns the next horizontal or vertical snap position based on the current
// camera preview snap position `current` and the movement. Returns `current` if
// the movement is not doable based on current snap position.
CameraPreviewSnapPosition GetCameraNextHorizontalSnapPosition(
CameraPreviewSnapPosition current,
bool going_left);
CameraPreviewSnapPosition GetCameraNextVerticalSnapPosition(
CameraPreviewSnapPosition current,
bool going_up);
// Notification Utils //
// The notification ID prefix used for notifications corresponding to captured
// images and videos.
constexpr char kScreenCaptureNotificationId[] = "capture_mode_notification";
// Constants related to the banner view on the image capture notifications.
constexpr int kBannerHeightDip = 36;
constexpr int kBannerHorizontalInsetDip = 12;
constexpr int kBannerVerticalInsetDip = 8;
constexpr int kBannerIconTextSpacingDip = 8;
constexpr int kBannerIconSizeDip = 20;
// Constants related to the play icon view for video capture notifications.
constexpr int kPlayIconSizeDip = 24;
constexpr int kPlayIconBackgroundCornerRadiusDip = 20;
constexpr gfx::Size kPlayIconViewSize{40, 40};
std::unique_ptr<views::View> CreateClipboardShortcutView();
// Creates the banner view that will show on top of the notification image.
std::unique_ptr<views::View> CreateBannerView();
// Creates the play icon view which shows on top of the video thumbnail in the
// notification.
std::unique_ptr<views::View> CreatePlayIconView();
// Returns the local center point of the given `layer`.
gfx::Point GetLocalCenterPoint(ui::Layer* layer);
// Returns a transform that scales the given `layer` by the given `scale` factor
// in both X and Y around its local center point.
gfx::Transform GetScaleTransformAboutCenter(ui::Layer* layer, float scale);
// Defines an object to hold the values of the camera preview size specs.
struct CameraPreviewSizeSpecs {
// The size to which the camera preview should be set under the current
// conditions.
const gfx::Size size;
// True if the expanded size of the camera preview is big enough to allow it
// to be collapsible. False otherwise.
const bool is_collapsible;
// Whether the camera preview should be hidden or shown. The visibility of the
// preview can be determined by a number of things, e.g.:
// - The surface within which the camera preview should be confined is too
// small.
// - We're inside a `kRegion` session and the region is being adjusted or
// empty.
const bool should_be_visible;
// True if the surface within which the camera preview is confined is too
// small, and the preview should be hidden.
const bool is_surface_too_small;
};
// Calculates the size specs of the camera preview which will be confined within
// the given `confine_bounds_size` and will be either expanded or collapsed
// based on the given `is_collapsed`.
ASH_EXPORT CameraPreviewSizeSpecs
CalculateCameraPreviewSizeSpecs(const gfx::Size& confine_bounds_size,
bool is_collapsed);
// Gets the top-most window that is capturable under the mouse/touch position.
// The windows that are not capturable include the camera preview widget and
// capture label. There will be a crash if the capture label widget gets picked
// since the snapshot code tries to snap a deleted window.
aura::Window* GetTopMostCapturableWindowAtPoint(const gfx::Point& screen_point);
bool GetWidgetCurrentVisibility(views::Widget* widget);
// Defines an object to hold the animation params used for setting the widget's
// visibility.
struct AnimationParams {
const base::TimeDelta animation_duration;
const gfx::Tween::Type tween_type;
// When it's true, the scale up transform should be applied in the fade in
// animiation.
const bool apply_scale_up_animation;
};
// Sets the visibility of the given `widget` to the given `target_visibility`
// with the given `animation_params`, returns true only if the
// `target_visibility` is different than the current.
bool SetWidgetVisibility(views::Widget* widget,
bool target_visibility,
std::optional<AnimationParams> animation_params);
// Gets the root window associated with `location_in_screen` if given, otherwise
// gets the root window associated with the `CursorManager`.
aura::Window* GetPreferredRootWindow(
std::optional<gfx::Point> location_in_screen = std::nullopt);
// Configures style for the `label_view` in the settings menu.
void ConfigLabelView(views::Label* label_view);
// Initializes the box layout for the `view` in the settings menu.
views::BoxLayout* CreateAndInitBoxLayoutForView(views::View* view);
// If the privacy indicators feature is enabled, the below function update the
// camera and microphone capture mode indicators according to the current state.
void MaybeUpdateCaptureModePrivacyIndicators();
ui::ColorProvider* GetColorProviderForNativeTheme();
// Returns true if the given located `event` is targeted on a window that is a
// descendant of the given `widget`. Note that `widget` can be provided as null
// if it no longer exists, in this case this function returns false.
bool IsEventTargetedOnWidget(const ui::LocatedEvent& event,
views::Widget* widget);
// Calculates the highlight layer bounds based on `center_point` which is in the
// coordinates of the window being recorded.
ASH_EXPORT gfx::Rect CalculateHighlightLayerBounds(
const gfx::PointF& center_point,
int highlight_layer_radius);
// Sets a highlight border to the `view` with given rounded corner radius and
// type.
void SetHighlightBorder(views::View* view,
int corner_radius,
views::HighlightBorder::Type type);
// Returns the frame header of the given `window` if any, nullptr otherwise.
ASH_EXPORT chromeos::FrameHeader* GetWindowFrameHeader(aura::Window* window);
// Returns the bounds within which the on-capture-surface UI elements (e.g. the
// selfie camera, or the demo tools key combo widgets) will be confined, when
// the given non-root `window` is being captured.
ASH_EXPORT gfx::Rect GetCaptureWindowConfineBounds(aura::Window* window);
// Returns the `partial_region_bounds` clamped to the bounds of the the
// `root_window`. It should only be called if in region video recording mode.
gfx::Rect GetEffectivePartialRegionBounds(
const gfx::Rect& partial_region_bounds,
aura::Window* root_window);
} // namespace capture_mode_util
} // namespace ash
#endif // ASH_CAPTURE_MODE_CAPTURE_MODE_UTIL_H_