blob: d35bf72b19c290b0c997cc4d0f0b95c928af3793 [file] [log] [blame]
// 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 CHROME_BROWSER_UI_VIEWS_ACCESSIBILITY_ACCESSIBILITY_FOCUS_HIGHLIGHT_H_
#define CHROME_BROWSER_UI_VIEWS_ACCESSIBILITY_ACCESSIBILITY_FOCUS_HIGHLIGHT_H_
#include <memory>
#include "base/callback_list.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
#include "components/prefs/pref_change_registrar.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/compositor/compositor_animation_observer.h"
#include "ui/compositor/layer_delegate.h"
#include "ui/gfx/geometry/rect.h"
class BrowserView;
namespace content {
struct FocusedNodeDetails;
} // namespace content
namespace ui {
class Compositor;
class Layer;
} // namespace ui
// AccessibilityFocusHighlight manages an always-on-top layer used to
// highlight the focused UI element for accessibility.
class AccessibilityFocusHighlight : public ui::LayerDelegate,
public ui::CompositorAnimationObserver,
public TabStripModelObserver {
public:
explicit AccessibilityFocusHighlight(BrowserView* browser_view);
~AccessibilityFocusHighlight() override;
// Disallow copy and assign.
AccessibilityFocusHighlight(const AccessibilityFocusHighlight&) = delete;
AccessibilityFocusHighlight& operator=(const AccessibilityFocusHighlight&) =
delete;
private:
FRIEND_TEST_ALL_PREFIXES(AccessibilityFocusHighlightBrowserTest,
DrawsHighlight);
FRIEND_TEST_ALL_PREFIXES(AccessibilityFocusHighlightBrowserTest,
FocusAppearance);
// For testing.
static void SetNoFadeForTesting();
static void SkipActivationCheckForTesting();
static void UseDefaultColorForTesting();
ui::Layer* GetLayerForTesting();
// Create the layer if needed, and set node_bounds_
void CreateOrUpdateLayer(gfx::Rect node_bounds);
// Get rid of the layer and stop animation.
void RemoveLayer();
// Handle preference changes by adding or removing observers as necessary.
void AddOrRemoveObservers();
// Handle focus change notifications.
void OnFocusChangedInPage(const content::FocusedNodeDetails& details);
// ui::LayerDelegate overrides:
void OnPaintLayer(const ui::PaintContext& context) override;
void OnDeviceScaleFactorChanged(float old_device_scale_factor,
float new_device_scale_factor) override {}
// CompositorAnimationObserver overrides:
void OnAnimationStep(base::TimeTicks timestamp) override;
void OnCompositingShuttingDown(ui::Compositor* compositor) override;
// TabStripModelObserver
void OnTabStripModelChanged(TabStripModel*,
const TabStripModelChange&,
const TabStripSelectionChange&) override;
// Compute the highlight color based on theme colors and defaults.
SkColor GetHighlightColor();
// Compute the opacity based on the fade in and fade out times.
// TODO(aboxhall): figure out how to use cubic beziers
float ComputeOpacity(base::TimeDelta time_since_layer_create,
base::TimeDelta time_since_focus_move);
// The layer, if visible.
std::unique_ptr<ui::Layer> layer_;
// The compositor associated with this layer.
raw_ptr<ui::Compositor> compositor_ = nullptr;
// The bounding rectangle of the focused object, relative to the layer.
gfx::Rect node_bounds_;
// Owns this.
raw_ptr<BrowserView> browser_view_;
// The time the layer was created and started fading in.
base::TimeTicks layer_created_time_;
// The most recent time the layer was updated because focus moved.
base::TimeTicks focus_last_changed_time_;
// Whether to skip fade in/fade out for testing.
static bool no_fade_for_testing_;
// The amount of time it should take for the highlight to fade in.
static base::TimeDelta fade_in_time_;
// The amount of time the highlight should persist between fading in and
// fading out.
static base::TimeDelta persist_time_;
// The amount of time it should take for the highlight to fade out.
static base::TimeDelta fade_out_time_;
// If set, draws the highlight even if the widget is not active.
static bool skip_activation_check_for_testing_;
// If set, don't check the system theme color.
static bool use_default_color_for_testing_;
// For observing browser preference notifications.
PrefChangeRegistrar profile_pref_registrar_;
// For observing focus notifications.
std::optional<base::CallbackListSubscription> focus_changed_subscription_;
};
#endif // CHROME_BROWSER_UI_VIEWS_ACCESSIBILITY_ACCESSIBILITY_FOCUS_HIGHLIGHT_H_