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 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
|
// Copyright 2019 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_SHELF_HOTSEAT_WIDGET_H_
#define ASH_SHELF_HOTSEAT_WIDGET_H_
#include <memory>
#include <optional>
#include "ash/ash_export.h"
#include "ash/public/cpp/metrics_util.h"
#include "ash/public/cpp/shelf_config.h"
#include "ash/public/cpp/shelf_types.h"
#include "ash/shelf/hotseat_transition_animator.h"
#include "ash/shelf/shelf_component.h"
#include "base/memory/raw_ptr.h"
#include "ui/views/widget/widget.h"
namespace aura {
class ScopedWindowTargeter;
}
namespace ash {
class ScrollableShelfView;
class Shelf;
class ShelfView;
class HotseatTransitionAnimator;
class HotseatWidgetDelegateView;
// The hotseat widget is part of the shelf and hosts app shortcuts.
class ASH_EXPORT HotseatWidget : public ShelfComponent,
public ShelfConfig::Observer,
public views::Widget {
public:
// Defines the hotseat transition types.
enum class StateTransition {
// Hotseat state transits between kShownHomeLauncher and kExtended.
kHomeLauncherAndExtended,
// Hotseat state transits between kShownHomeLauncher and kHidden.
kHomeLauncherAndHidden,
// Hotseat state transits between kHidden and kExtended.
kHiddenAndExtended,
kOther
};
// Scoped class to notify HotseatWidget of hotseat state transition in
// progress. We should not calculate the state transition simply in
// HotseatWidget::SetState(). Otherwise it is hard to reset when the
// transition completes.
class ScopedInStateTransition {
public:
ScopedInStateTransition(HotseatWidget* hotseat_widget,
HotseatState old_state,
HotseatState target_state);
~ScopedInStateTransition();
ScopedInStateTransition(const ScopedInStateTransition& rhs) = delete;
ScopedInStateTransition& operator=(const ScopedInStateTransition& rhs) =
delete;
private:
raw_ptr<HotseatWidget> hotseat_widget_ = nullptr;
};
HotseatWidget();
HotseatWidget(const HotseatWidget&) = delete;
HotseatWidget& operator=(const HotseatWidget&) = delete;
~HotseatWidget() override;
// Returns whether the hotseat background should be shown.
static bool ShouldShowHotseatBackground();
// Initializes the widget, sets its contents view and basic properties.
void Initialize(aura::Window* container, Shelf* shelf);
// Initializes the animation metrics reporter responsible for recording
// animation performance during hotseat state changes, and attaches
// |delegate_view_| as an observer.
void OnHotseatTransitionAnimatorCreated(HotseatTransitionAnimator* animator);
// views::Widget:
void OnMouseEvent(ui::MouseEvent* event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
bool OnNativeWidgetActivationChanged(bool active) override;
// ShelfConfig::Observer:
void OnShelfConfigUpdated() override;
// Whether the widget is in the extended position.
bool IsExtended() const;
// Finds the first or last focusable app shortcut and focuses it.
void FocusFirstOrLastFocusableChild(bool last);
// Notifies children of tablet mode state changes.
void OnTabletModeChanged();
// Returns the target opacity for the shelf view given current conditions.
float CalculateShelfViewOpacity() const;
// Updates the bounds of the translucent background which functions as the
// hotseat background.
void UpdateTranslucentBackground();
void InitializeAccessibilityProperties();
// Calculates the hotseat y position for |hotseat_target_state| in screen
// coordinates.
int CalculateHotseatYInScreen(HotseatState hotseat_target_state) const;
// Calculates the hotseat target bounds's size for the given target state.
gfx::Size CalculateTargetBoundsSize(HotseatState hotseat_target_state) const;
// Calculates space available for app bar if shown inline with shelf.
gfx::Size CalculateInlineAppBarSize() const;
// Takes insets to reserve when calculating bounds.
void ReserveSpaceForAdjacentWidgets(const gfx::Insets& space);
// ShelfComponent:
void CalculateTargetBounds() override;
gfx::Rect GetTargetBounds() const override;
void UpdateLayout(bool animate) override;
void UpdateTargetBoundsForGesture(int shelf_position) override;
// TODO(manucornet): Remove this method once all the hotseat layout
// code has moved to this class.
void set_target_bounds(gfx::Rect target_bounds) {
target_bounds_ = target_bounds;
}
gfx::Size GetTranslucentBackgroundSize() const;
bool IsShowingShelfMenu() const;
// Whether the event is located in the hotseat area containing shelf apps.
bool EventTargetsShelfView(const ui::LocatedEvent& event) const;
ShelfView* GetShelfView();
const ShelfView* GetShelfView() const;
// Returns the hotseat height (or width for side shelf).
int GetHotseatSize() const;
// Returns the drag distance required to fully show the hotseat widget from
// the hidden state.
int GetHotseatFullDragAmount() const;
// Updates the target hotseat density, if needed. Returns whether
// |target_hotseat_density_| has changed after calling this method.
bool UpdateTargetHotseatDensityIfNeeded();
// Returns the background blur of the |translucent_background_|, for tests.
int GetHotseatBackgroundBlurForTest() const;
// Returns whether the translucent background is visible, for tests.
bool GetIsTranslucentBackgroundVisibleForTest() const;
metrics_util::ReportCallback GetTranslucentBackgroundReportCallback();
void SetState(HotseatState state);
HotseatState state() const { return state_; }
ScrollableShelfView* scrollable_shelf_view() {
return scrollable_shelf_view_;
}
const ScrollableShelfView* scrollable_shelf_view() const {
return scrollable_shelf_view_;
}
// Whether the widget is in the extended position because of a direct
// manual user intervention (dragging the hotseat into its extended state).
// This will return |false| after any visible change in the shelf
// configuration.
bool is_manually_extended() const { return is_manually_extended_; }
void set_manually_extended(bool value) { is_manually_extended_ = value; }
HotseatDensity target_hotseat_density() const {
return target_hotseat_density_;
}
// The layer that should be used to animate hotseat bounds while showing the
// home to overview contextual nudge.
ui::Layer* GetLayerForNudgeAnimation();
// Returns if the shelf is going to be overflown.
bool CalculateShelfOverflow(bool use_target_bounds) const;
private:
struct LayoutInputs {
gfx::Rect bounds;
float shelf_view_opacity = 0.0f;
bool is_active_session_state = false;
gfx::Insets reserved_space_;
bool operator==(const LayoutInputs& other) const {
return bounds == other.bounds &&
shelf_view_opacity == other.shelf_view_opacity &&
is_active_session_state == other.is_active_session_state &&
reserved_space_ == other.reserved_space_;
}
};
// Collects the inputs for layout.
LayoutInputs GetLayoutInputs() const;
// May update the hotseat widget's target in account of app scaling.
void MaybeAdjustTargetBoundsForAppScaling(HotseatState hotseat_target_state);
// Calculates the target hotseat density.
HotseatDensity CalculateTargetHotseatDensity() const;
// Animates the hotseat to the target opacity/bounds.
void LayoutHotseatByAnimation(double target_opacity,
const gfx::Rect& target_bounds);
// Start the animation designed specifically for |state_transition|.
void StartHotseatTransitionAnimation(StateTransition state_transition,
double target_opacity,
const gfx::Rect& target_bounds);
// Starts the default bounds/opacity animation.
void StartNormalBoundsAnimation(double target_opacity,
const gfx::Rect& target_bounds);
// The set of inputs that impact this widget's layout. The assumption is that
// this widget needs a relayout if, and only if, one or more of these has
// changed.
std::optional<LayoutInputs> layout_inputs_;
gfx::Rect target_bounds_;
// The size that |target_bounds_| would have in kShownHomeLauncher state.
// Used to calculate hotseat density state.
gfx::Size target_size_for_shown_state_;
HotseatState state_ = HotseatState::kNone;
// Indicates the type of the hotseat state transition in progress.
std::optional<StateTransition> state_transition_in_progress_;
raw_ptr<Shelf> shelf_ = nullptr;
// View containing the shelf items within an active user session. Owned by
// the views hierarchy.
raw_ptr<ScrollableShelfView, DanglingUntriaged> scrollable_shelf_view_ =
nullptr;
// The contents view of this widget. Contains |shelf_view_| and the background
// of the hotseat.
raw_ptr<HotseatWidgetDelegateView> delegate_view_ = nullptr;
// Whether the widget is currently extended because the user has manually
// dragged it. This will be reset with any visible shelf configuration change.
bool is_manually_extended_ = false;
// Indicates the target hotseat density. When app scaling feature is enabled,
// hotseat may become denser if there is insufficient view space to
// accommodate all app icons without scrolling.
HotseatDensity target_hotseat_density_ = HotseatDensity::kNormal;
// The window targeter installed on the hotseat. Filters out events which land
// on the non visible portion of the hotseat, or events that reach the hotseat
// during an animation.
std::unique_ptr<aura::ScopedWindowTargeter> hotseat_window_targeter_;
// Space reserved by other widgets to exclude when calculating bounds and hit
// area.
gfx::Insets reserved_space_;
};
} // namespace ash
#endif // ASH_SHELF_HOTSEAT_WIDGET_H_
|