shelf.cc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/shelf/shelf.h"
  5. #include <memory>
  6. #include "ash/animation/animation_change_type.h"
  7. #include "ash/app_list/app_list_controller_impl.h"
  8. #include "ash/constants/ash_features.h"
  9. #include "ash/constants/ash_switches.h"
  10. #include "ash/public/cpp/keyboard/keyboard_controller_observer.h"
  11. #include "ash/public/cpp/shelf_item_delegate.h"
  12. #include "ash/public/cpp/shelf_model.h"
  13. #include "ash/public/cpp/shelf_types.h"
  14. #include "ash/public/cpp/shell_window_ids.h"
  15. #include "ash/root_window_controller.h"
  16. #include "ash/shelf/hotseat_widget.h"
  17. #include "ash/shelf/login_shelf_widget.h"
  18. #include "ash/shelf/shelf_controller.h"
  19. #include "ash/shelf/shelf_focus_cycler.h"
  20. #include "ash/shelf/shelf_layout_manager.h"
  21. #include "ash/shelf/shelf_layout_manager_observer.h"
  22. #include "ash/shelf/shelf_navigation_widget.h"
  23. #include "ash/shelf/shelf_observer.h"
  24. #include "ash/shelf/shelf_tooltip_manager.h"
  25. #include "ash/shelf/shelf_widget.h"
  26. #include "ash/shell.h"
  27. #include "ash/system/status_area_widget.h"
  28. #include "ash/wm/work_area_insets.h"
  29. #include "base/bind.h"
  30. #include "base/callback_helpers.h"
  31. #include "base/check.h"
  32. #include "base/i18n/rtl.h"
  33. #include "base/memory/weak_ptr.h"
  34. #include "base/metrics/histogram_macros.h"
  35. #include "base/notreached.h"
  36. #include "ui/display/types/display_constants.h"
  37. #include "ui/gfx/geometry/rect.h"
  38. namespace ash {
  39. namespace {
  40. bool IsAppListBackground(ShelfBackgroundType background_type) {
  41. switch (background_type) {
  42. case ShelfBackgroundType::kAppList:
  43. case ShelfBackgroundType::kHomeLauncher:
  44. case ShelfBackgroundType::kMaximizedWithAppList:
  45. return true;
  46. case ShelfBackgroundType::kDefaultBg:
  47. case ShelfBackgroundType::kMaximized:
  48. case ShelfBackgroundType::kOobe:
  49. case ShelfBackgroundType::kLogin:
  50. case ShelfBackgroundType::kLoginNonBlurredWallpaper:
  51. case ShelfBackgroundType::kOverview:
  52. case ShelfBackgroundType::kInApp:
  53. return false;
  54. }
  55. }
  56. bool IsBottomAlignment(ShelfAlignment alignment) {
  57. return alignment == ShelfAlignment::kBottom ||
  58. alignment == ShelfAlignment::kBottomLocked;
  59. }
  60. } // namespace
  61. // Records smoothness of bounds animations for the HotseatWidget.
  62. class HotseatWidgetAnimationMetricsReporter {
  63. public:
  64. // The different kinds of hotseat elements.
  65. enum class HotseatElementType {
  66. // The Hotseat Widget.
  67. kWidget,
  68. // The Hotseat Widget's translucent background.
  69. kTranslucentBackground
  70. };
  71. explicit HotseatWidgetAnimationMetricsReporter(
  72. HotseatElementType hotseat_element)
  73. : hotseat_element_(hotseat_element) {}
  74. ~HotseatWidgetAnimationMetricsReporter() = default;
  75. void ReportSmoothness(HotseatState target_state, int smoothness) {
  76. switch (target_state) {
  77. case HotseatState::kShownClamshell:
  78. case HotseatState::kShownHomeLauncher:
  79. if (hotseat_element_ == HotseatElementType::kWidget) {
  80. UMA_HISTOGRAM_PERCENTAGE(
  81. "Ash.HotseatWidgetAnimation.Widget.AnimationSmoothness."
  82. "TransitionToShownHotseat",
  83. smoothness);
  84. } else {
  85. UMA_HISTOGRAM_PERCENTAGE(
  86. "Ash.HotseatWidgetAnimation.TranslucentBackground."
  87. "AnimationSmoothness.TransitionToShownHotseat",
  88. smoothness);
  89. }
  90. break;
  91. case HotseatState::kExtended:
  92. if (hotseat_element_ == HotseatElementType::kWidget) {
  93. UMA_HISTOGRAM_PERCENTAGE(
  94. "Ash.HotseatWidgetAnimation.Widget.AnimationSmoothness."
  95. "TransitionToExtendedHotseat",
  96. smoothness);
  97. } else {
  98. UMA_HISTOGRAM_PERCENTAGE(
  99. "Ash.HotseatWidgetAnimation.TranslucentBackground."
  100. "AnimationSmoothness.TransitionToExtendedHotseat",
  101. smoothness);
  102. }
  103. break;
  104. case HotseatState::kHidden:
  105. if (hotseat_element_ == HotseatElementType::kWidget) {
  106. UMA_HISTOGRAM_PERCENTAGE(
  107. "Ash.HotseatWidgetAnimation.Widget.AnimationSmoothness."
  108. "TransitionToHiddenHotseat",
  109. smoothness);
  110. } else {
  111. UMA_HISTOGRAM_PERCENTAGE(
  112. "Ash.HotseatWidgetAnimation.TranslucentBackground."
  113. "AnimationSmoothness.TransitionToHiddenHotseat",
  114. smoothness);
  115. }
  116. break;
  117. case HotseatState::kNone:
  118. NOTREACHED();
  119. break;
  120. }
  121. }
  122. metrics_util::ReportCallback GetReportCallback(HotseatState target_state) {
  123. DCHECK_NE(target_state, HotseatState::kNone);
  124. return metrics_util::ForSmoothness(base::BindRepeating(
  125. &HotseatWidgetAnimationMetricsReporter::ReportSmoothness,
  126. weak_ptr_factory_.GetWeakPtr(), target_state));
  127. }
  128. private:
  129. // The element that is reporting an animation.
  130. const HotseatElementType hotseat_element_;
  131. base::WeakPtrFactory<HotseatWidgetAnimationMetricsReporter> weak_ptr_factory_{
  132. this};
  133. };
  134. // An animation metrics reporter for the shelf navigation widget.
  135. class ASH_EXPORT NavigationWidgetAnimationMetricsReporter {
  136. public:
  137. NavigationWidgetAnimationMetricsReporter() = default;
  138. ~NavigationWidgetAnimationMetricsReporter() = default;
  139. NavigationWidgetAnimationMetricsReporter(
  140. const NavigationWidgetAnimationMetricsReporter&) = delete;
  141. NavigationWidgetAnimationMetricsReporter& operator=(
  142. const NavigationWidgetAnimationMetricsReporter&) = delete;
  143. void ReportSmoothness(HotseatState target_hotseat_state, int smoothness) {
  144. switch (target_hotseat_state) {
  145. case HotseatState::kShownClamshell:
  146. case HotseatState::kShownHomeLauncher:
  147. UMA_HISTOGRAM_PERCENTAGE(
  148. "Ash.NavigationWidget.Widget.AnimationSmoothness."
  149. "TransitionToShownHotseat",
  150. smoothness);
  151. break;
  152. case HotseatState::kExtended:
  153. UMA_HISTOGRAM_PERCENTAGE(
  154. "Ash.NavigationWidget.Widget.AnimationSmoothness."
  155. "TransitionToExtendedHotseat",
  156. smoothness);
  157. break;
  158. case HotseatState::kHidden:
  159. UMA_HISTOGRAM_PERCENTAGE(
  160. "Ash.NavigationWidget.Widget.AnimationSmoothness."
  161. "TransitionToHiddenHotseat",
  162. smoothness);
  163. break;
  164. case HotseatState::kNone:
  165. NOTREACHED();
  166. break;
  167. }
  168. }
  169. metrics_util::ReportCallback GetReportCallback(
  170. HotseatState target_hotseat_state) {
  171. DCHECK_NE(target_hotseat_state, HotseatState::kNone);
  172. return metrics_util::ForSmoothness(base::BindRepeating(
  173. &NavigationWidgetAnimationMetricsReporter::ReportSmoothness,
  174. weak_ptr_factory_.GetWeakPtr(), target_hotseat_state));
  175. }
  176. private:
  177. base::WeakPtrFactory<NavigationWidgetAnimationMetricsReporter>
  178. weak_ptr_factory_{this};
  179. };
  180. // Shelf::AutoHideEventHandler -----------------------------------------------
  181. // Forwards mouse and gesture events to ShelfLayoutManager for auto-hide.
  182. class Shelf::AutoHideEventHandler : public ui::EventHandler {
  183. public:
  184. explicit AutoHideEventHandler(Shelf* shelf) : shelf_(shelf) {
  185. Shell::Get()->AddPreTargetHandler(this);
  186. }
  187. AutoHideEventHandler(const AutoHideEventHandler&) = delete;
  188. AutoHideEventHandler& operator=(const AutoHideEventHandler&) = delete;
  189. ~AutoHideEventHandler() override {
  190. Shell::Get()->RemovePreTargetHandler(this);
  191. }
  192. // ui::EventHandler:
  193. void OnMouseEvent(ui::MouseEvent* event) override {
  194. shelf_->shelf_layout_manager()->UpdateAutoHideForMouseEvent(
  195. event, static_cast<aura::Window*>(event->target()));
  196. }
  197. void OnGestureEvent(ui::GestureEvent* event) override {
  198. shelf_->shelf_layout_manager()->ProcessGestureEventOfAutoHideShelf(
  199. event, static_cast<aura::Window*>(event->target()));
  200. }
  201. void OnTouchEvent(ui::TouchEvent* event) override {
  202. if (shelf_->auto_hide_behavior() != ShelfAutoHideBehavior::kAlways)
  203. return;
  204. // The event target should be the shelf widget or the hotseat widget.
  205. if (!shelf_->shelf_layout_manager()->IsShelfWindow(
  206. static_cast<aura::Window*>(event->target()))) {
  207. return;
  208. }
  209. // The touch-pressing event may hide the shelf. Lock the shelf's auto hide
  210. // state to give the shelf a chance to handle the touch event before it
  211. // being hidden.
  212. ShelfLayoutManager* shelf_layout_manager = shelf_->shelf_layout_manager();
  213. if (event->type() == ui::ET_TOUCH_PRESSED && shelf_->IsVisible()) {
  214. shelf_layout_manager->LockAutoHideState(true);
  215. } else if (event->type() == ui::ET_TOUCH_RELEASED ||
  216. event->type() == ui::ET_TOUCH_CANCELLED) {
  217. // Unlock auto hide (and eventually recompute auto hide state).
  218. shelf_layout_manager->LockAutoHideState(false);
  219. }
  220. }
  221. private:
  222. Shelf* shelf_;
  223. };
  224. // Shelf::AutoDimEventHandler -----------------------------------------------
  225. // Handles mouse and touch events and determines whether ShelfLayoutManager
  226. // should update shelf opacity for auto-dimming.
  227. class Shelf::AutoDimEventHandler : public ui::EventHandler,
  228. public ShelfObserver {
  229. public:
  230. explicit AutoDimEventHandler(Shelf* shelf) : shelf_(shelf) {
  231. Shell::Get()->AddPreTargetHandler(this);
  232. shelf_observation_.Observe(shelf_);
  233. UndimShelf();
  234. }
  235. AutoDimEventHandler(const AutoDimEventHandler&) = delete;
  236. AutoDimEventHandler& operator=(const AutoDimEventHandler&) = delete;
  237. ~AutoDimEventHandler() override {
  238. Shell::Get()->RemovePreTargetHandler(this);
  239. }
  240. // ui::EventHandler:
  241. void OnMouseEvent(ui::MouseEvent* event) override {
  242. if (shelf_->shelf_layout_manager()->IsShelfWindow(
  243. static_cast<aura::Window*>(event->target()))) {
  244. UndimShelf();
  245. }
  246. }
  247. void OnTouchEvent(ui::TouchEvent* event) override {
  248. if (shelf_->shelf_layout_manager()->IsShelfWindow(
  249. static_cast<aura::Window*>(event->target()))) {
  250. UndimShelf();
  251. }
  252. }
  253. void StartDimShelfTimer() {
  254. dim_shelf_timer_.Start(
  255. FROM_HERE, kDimDelay,
  256. base::BindOnce(&AutoDimEventHandler::DimShelf, base::Unretained(this)));
  257. }
  258. void DimShelf() {
  259. // Attempt to dim the shelf. Stop the |dim_shelf_timer_| if successful.
  260. if (shelf_->shelf_layout_manager()->SetDimmed(true))
  261. dim_shelf_timer_.Stop();
  262. }
  263. // Sets shelf as active and sets timer to mark shelf as inactive.
  264. void UndimShelf() {
  265. shelf_->shelf_layout_manager()->SetDimmed(false);
  266. StartDimShelfTimer();
  267. }
  268. bool HasDimShelfTimer() { return dim_shelf_timer_.IsRunning(); }
  269. // ShelfObserver:
  270. void OnAutoHideStateChanged(ShelfAutoHideState new_state) override {
  271. // Shelf should be undimmed when it is shown.
  272. if (new_state == ShelfAutoHideState::SHELF_AUTO_HIDE_SHOWN)
  273. UndimShelf();
  274. }
  275. // ShelfObserver:
  276. void WillChangeVisibilityState(ShelfVisibilityState new_state) override {
  277. // Shelf should be undimmed when it is shown.
  278. if (new_state != ShelfVisibilityState::SHELF_HIDDEN)
  279. UndimShelf();
  280. }
  281. private:
  282. // Unowned pointer to the shelf that owns this event handler.
  283. Shelf* shelf_;
  284. // OneShotTimer that dims shelf due to inactivity.
  285. base::OneShotTimer dim_shelf_timer_;
  286. // An observer that notifies the AutoDimHandler that shelf visibility has
  287. // changed.
  288. base::ScopedObservation<Shelf, ShelfObserver> shelf_observation_{this};
  289. // Delay before dimming the shelf.
  290. const base::TimeDelta kDimDelay = base::Seconds(5);
  291. };
  292. // Shelf ---------------------------------------------------------------------
  293. Shelf::Shelf()
  294. : shelf_locking_manager_(this),
  295. shelf_focus_cycler_(std::make_unique<ShelfFocusCycler>(this)),
  296. tooltip_(std::make_unique<ShelfTooltipManager>(this)) {}
  297. Shelf::~Shelf() = default;
  298. // static
  299. Shelf* Shelf::ForWindow(aura::Window* window) {
  300. return RootWindowController::ForWindow(window)->shelf();
  301. }
  302. // static
  303. void Shelf::LaunchShelfItem(int item_index) {
  304. const int item_count = ShelfModel::Get()->item_count();
  305. // A negative argument will launch the last app. A positive argument will
  306. // launch the app at the corresponding index, unless it's higher than the
  307. // total number of apps, in which case we do nothing.
  308. if (item_index >= item_count)
  309. return;
  310. const int found_index = item_index >= 0 ? item_index : item_count - 1;
  311. // Set this one as active (or advance to the next item of its kind).
  312. ActivateShelfItem(found_index);
  313. }
  314. // static
  315. void Shelf::ActivateShelfItem(int item_index) {
  316. ActivateShelfItemOnDisplay(item_index, display::kInvalidDisplayId);
  317. }
  318. // static
  319. void Shelf::ActivateShelfItemOnDisplay(int item_index, int64_t display_id) {
  320. const ShelfModel* shelf_model = ShelfModel::Get();
  321. const ShelfItem& item = shelf_model->items()[item_index];
  322. ShelfItemDelegate* item_delegate = shelf_model->GetShelfItemDelegate(item.id);
  323. std::unique_ptr<ui::Event> event = std::make_unique<ui::KeyEvent>(
  324. ui::ET_KEY_RELEASED, ui::VKEY_UNKNOWN, ui::EF_NONE);
  325. item_delegate->ItemSelected(std::move(event), display_id, LAUNCH_FROM_SHELF,
  326. base::DoNothing(), base::NullCallback());
  327. }
  328. // static
  329. void Shelf::UpdateShelfVisibility() {
  330. for (auto* root : Shell::Get()->GetAllRootWindows()) {
  331. Shelf::ForWindow(root)->UpdateVisibilityState();
  332. }
  333. }
  334. void Shelf::CreateNavigationWidget(aura::Window* container) {
  335. DCHECK(container);
  336. DCHECK(!navigation_widget_);
  337. navigation_widget_ = std::make_unique<ShelfNavigationWidget>(
  338. this, hotseat_widget()->GetShelfView());
  339. navigation_widget_->Initialize(container);
  340. navigation_widget_metrics_reporter_ =
  341. std::make_unique<NavigationWidgetAnimationMetricsReporter>();
  342. }
  343. void Shelf::CreateHotseatWidget(aura::Window* container) {
  344. DCHECK(container);
  345. DCHECK(!hotseat_widget_);
  346. hotseat_widget_ = std::make_unique<HotseatWidget>();
  347. translucent_background_metrics_reporter_ =
  348. std::make_unique<HotseatWidgetAnimationMetricsReporter>(
  349. HotseatWidgetAnimationMetricsReporter::HotseatElementType::
  350. kTranslucentBackground);
  351. hotseat_widget_->Initialize(container, this);
  352. shelf_widget_->RegisterHotseatWidget(hotseat_widget());
  353. hotseat_transition_metrics_reporter_ =
  354. std::make_unique<HotseatWidgetAnimationMetricsReporter>(
  355. HotseatWidgetAnimationMetricsReporter::HotseatElementType::kWidget);
  356. }
  357. void Shelf::CreateStatusAreaWidget(aura::Window* shelf_container) {
  358. DCHECK(shelf_container);
  359. DCHECK(!status_area_widget_);
  360. status_area_widget_ =
  361. std::make_unique<StatusAreaWidget>(shelf_container, this);
  362. status_area_widget_->Initialize();
  363. }
  364. void Shelf::CreateShelfWidget(aura::Window* root) {
  365. DCHECK(!shelf_widget_);
  366. aura::Window* shelf_container =
  367. root->GetChildById(kShellWindowId_ShelfContainer);
  368. shelf_widget_ = std::make_unique<ShelfWidget>(this);
  369. DCHECK(!shelf_layout_manager_);
  370. shelf_layout_manager_ = shelf_widget_->shelf_layout_manager();
  371. shelf_layout_manager_->AddObserver(this);
  372. // Create the various shelf components.
  373. CreateHotseatWidget(shelf_container);
  374. CreateNavigationWidget(shelf_container);
  375. if (features::IsUseLoginShelfWidgetEnabled()) {
  376. login_shelf_widget_ =
  377. std::make_unique<LoginShelfWidget>(/*shelf=*/this, shelf_container);
  378. }
  379. // Must occur after |shelf_widget_| is constructed because the system tray
  380. // constructors call back into Shelf::shelf_widget().
  381. CreateStatusAreaWidget(shelf_container);
  382. shelf_widget_->Initialize(shelf_container);
  383. shelf_widget_->GetNativeWindow()->parent()->StackChildAtBottom(
  384. shelf_widget_->GetNativeWindow());
  385. // The Hotseat should be above everything in the shelf.
  386. hotseat_widget()->StackAtTop();
  387. }
  388. void Shelf::ShutdownShelfWidget() {
  389. for (auto& observer : observers_)
  390. observer.OnShelfShuttingDown();
  391. // Remove observers prior to destroying child widgets, this prevents
  392. // activation changes from triggering during shutdown, see
  393. // https://crbug.com/1307898.
  394. shelf_widget_->Shutdown();
  395. // The contents view of the hotseat widget may rely on the status area widget.
  396. // So do explicit destruction here.
  397. hotseat_widget_.reset();
  398. status_area_widget_.reset();
  399. navigation_widget_.reset();
  400. login_shelf_widget_.reset();
  401. }
  402. void Shelf::DestroyShelfWidget() {
  403. DCHECK(shelf_widget_);
  404. shelf_widget_.reset();
  405. }
  406. bool Shelf::IsVisible() const {
  407. return shelf_layout_manager_->IsVisible();
  408. }
  409. const aura::Window* Shelf::GetWindow() const {
  410. return shelf_widget_ ? shelf_widget_->GetNativeWindow() : nullptr;
  411. }
  412. aura::Window* Shelf::GetWindow() {
  413. return const_cast<aura::Window*>(const_cast<const Shelf*>(this)->GetWindow());
  414. }
  415. void Shelf::SetAlignment(ShelfAlignment alignment) {
  416. if (!shelf_widget_)
  417. return;
  418. if (alignment_ == alignment)
  419. return;
  420. if (shelf_locking_manager_.is_locked() &&
  421. alignment != ShelfAlignment::kBottomLocked) {
  422. shelf_locking_manager_.set_stored_alignment(alignment);
  423. return;
  424. }
  425. bool needs_relayout =
  426. !IsBottomAlignment(alignment_) || !IsBottomAlignment(alignment);
  427. ShelfAlignment old_alignment = alignment_;
  428. alignment_ = alignment;
  429. tooltip_->Close();
  430. if (needs_relayout) {
  431. shelf_layout_manager_->LayoutShelf();
  432. Shell::Get()->NotifyShelfAlignmentChanged(GetWindow()->GetRootWindow(),
  433. old_alignment);
  434. }
  435. }
  436. bool IsHorizontalAlignment(ShelfAlignment alignment) {
  437. switch (alignment) {
  438. case ShelfAlignment::kBottom:
  439. case ShelfAlignment::kBottomLocked:
  440. return true;
  441. case ShelfAlignment::kLeft:
  442. case ShelfAlignment::kRight:
  443. return false;
  444. }
  445. NOTREACHED();
  446. return true;
  447. }
  448. bool Shelf::IsHorizontalAlignment() const {
  449. return ash::IsHorizontalAlignment(alignment_);
  450. }
  451. void Shelf::SetAutoHideBehavior(ShelfAutoHideBehavior auto_hide_behavior) {
  452. DCHECK(shelf_layout_manager_);
  453. if (auto_hide_behavior_ == auto_hide_behavior)
  454. return;
  455. auto_hide_behavior_ = auto_hide_behavior;
  456. for (auto& observer : observers_)
  457. observer.OnShelfAutoHideBehaviorChanged();
  458. }
  459. ShelfAutoHideState Shelf::GetAutoHideState() const {
  460. return shelf_layout_manager_->auto_hide_state();
  461. }
  462. void Shelf::UpdateAutoHideState() {
  463. shelf_layout_manager_->UpdateAutoHideState();
  464. }
  465. ShelfBackgroundType Shelf::GetBackgroundType() const {
  466. return shelf_widget_ ? shelf_widget_->GetBackgroundType()
  467. : ShelfBackgroundType::kDefaultBg;
  468. }
  469. void Shelf::UpdateVisibilityState() {
  470. if (shelf_layout_manager_)
  471. shelf_layout_manager_->UpdateVisibilityState();
  472. }
  473. void Shelf::MaybeUpdateShelfBackground() {
  474. if (!shelf_layout_manager_)
  475. return;
  476. shelf_layout_manager_->MaybeUpdateShelfBackground(
  477. AnimationChangeType::ANIMATE);
  478. }
  479. ShelfVisibilityState Shelf::GetVisibilityState() const {
  480. return shelf_layout_manager_ ? shelf_layout_manager_->visibility_state()
  481. : SHELF_HIDDEN;
  482. }
  483. gfx::Rect Shelf::GetShelfBoundsInScreen() const {
  484. return shelf_widget()->GetTargetBounds();
  485. }
  486. gfx::Rect Shelf::GetIdealBounds() const {
  487. return shelf_layout_manager_->GetIdealBounds();
  488. }
  489. gfx::Rect Shelf::GetIdealBoundsForWorkAreaCalculation() {
  490. return shelf_layout_manager_->GetIdealBoundsForWorkAreaCalculation();
  491. }
  492. gfx::Rect Shelf::GetScreenBoundsOfItemIconForWindow(aura::Window* window) {
  493. if (!shelf_widget_)
  494. return gfx::Rect();
  495. return shelf_widget_->GetScreenBoundsOfItemIconForWindow(window);
  496. }
  497. bool Shelf::ProcessGestureEvent(const ui::GestureEvent& event) {
  498. // Can be called at login screen.
  499. if (!shelf_layout_manager_)
  500. return false;
  501. return shelf_layout_manager_->ProcessGestureEvent(event);
  502. }
  503. void Shelf::ProcessMouseEvent(const ui::MouseEvent& event) {
  504. if (shelf_layout_manager_)
  505. shelf_layout_manager_->ProcessMouseEventFromShelf(event);
  506. }
  507. void Shelf::ProcessScrollEvent(ui::ScrollEvent* event) {
  508. if (event->finger_count() != 2 || event->type() != ui::ET_SCROLL)
  509. return;
  510. if (!shelf_layout_manager_->is_active_session_state())
  511. return;
  512. // Productivity launcher does not show or hide on scroll events. The legacy
  513. // peeking launcher had this behavior, but it doesn't make sense for a bubble.
  514. if (features::IsProductivityLauncherEnabled())
  515. return;
  516. auto* app_list_controller = Shell::Get()->app_list_controller();
  517. DCHECK(app_list_controller);
  518. // If the App List is not visible, send Scroll events to the
  519. // |shelf_layout_manager_| because these events are used to show the App
  520. // List.
  521. if (app_list_controller->IsVisible(shelf_layout_manager_->display_.id())) {
  522. app_list_controller->ProcessScrollEvent(*event);
  523. } else {
  524. shelf_layout_manager_->ProcessScrollEventFromShelf(event);
  525. }
  526. event->SetHandled();
  527. }
  528. void Shelf::ProcessMouseWheelEvent(ui::MouseWheelEvent* event) {
  529. if (!shelf_layout_manager_->is_active_session_state() ||
  530. !IsHorizontalAlignment())
  531. return;
  532. // Productivity launcher does not show or hide on wheel events. The legacy
  533. // peeking launcher had this behavior, but it doesn't make sense for a bubble.
  534. if (features::IsProductivityLauncherEnabled())
  535. return;
  536. auto* app_list_controller = Shell::Get()->app_list_controller();
  537. DCHECK(app_list_controller);
  538. // If the App List is not visible, send MouseWheel events to the
  539. // |shelf_layout_manager_| because these events are used to show the App List.
  540. if (app_list_controller->IsVisible(shelf_layout_manager_->display_.id())) {
  541. app_list_controller->ProcessMouseWheelEvent(*event);
  542. } else {
  543. shelf_layout_manager_->ProcessMouseWheelEventFromShelf(event);
  544. }
  545. event->SetHandled();
  546. }
  547. void Shelf::AddObserver(ShelfObserver* observer) {
  548. observers_.AddObserver(observer);
  549. }
  550. void Shelf::RemoveObserver(ShelfObserver* observer) {
  551. observers_.RemoveObserver(observer);
  552. }
  553. void Shelf::NotifyShelfIconPositionsChanged() {
  554. for (auto& observer : observers_)
  555. observer.OnShelfIconPositionsChanged();
  556. }
  557. StatusAreaWidget* Shelf::GetStatusAreaWidget() const {
  558. return shelf_widget_ ? shelf_widget_->status_area_widget() : nullptr;
  559. }
  560. gfx::Rect Shelf::GetSystemTrayAnchorRect() const {
  561. gfx::Rect work_area = GetWorkAreaInsets()->user_work_area_bounds();
  562. switch (alignment_) {
  563. case ShelfAlignment::kBottom:
  564. case ShelfAlignment::kBottomLocked:
  565. return gfx::Rect(
  566. base::i18n::IsRTL() ? work_area.x() : work_area.right() - 1,
  567. work_area.bottom() - 1, 0, 0);
  568. case ShelfAlignment::kLeft:
  569. return gfx::Rect(work_area.x(), work_area.bottom() - 1, 0, 0);
  570. case ShelfAlignment::kRight:
  571. return gfx::Rect(work_area.right() - 1, work_area.bottom() - 1, 0, 0);
  572. }
  573. NOTREACHED();
  574. return gfx::Rect();
  575. }
  576. bool Shelf::ShouldHideOnSecondaryDisplay(session_manager::SessionState state) {
  577. if (Shell::GetPrimaryRootWindowController()->shelf() == this)
  578. return false;
  579. return state != session_manager::SessionState::ACTIVE;
  580. }
  581. void Shelf::SetVirtualKeyboardBoundsForTesting(const gfx::Rect& bounds) {
  582. KeyboardStateDescriptor state;
  583. state.is_visible = !bounds.IsEmpty();
  584. state.visual_bounds = bounds;
  585. state.occluded_bounds_in_screen = bounds;
  586. state.displaced_bounds_in_screen = gfx::Rect();
  587. WorkAreaInsets* work_area_insets = GetWorkAreaInsets();
  588. work_area_insets->OnKeyboardVisibilityChanged(state.is_visible);
  589. work_area_insets->OnKeyboardVisibleBoundsChanged(state.visual_bounds);
  590. work_area_insets->OnKeyboardOccludedBoundsChanged(
  591. state.occluded_bounds_in_screen);
  592. work_area_insets->OnKeyboardDisplacingBoundsChanged(
  593. state.displaced_bounds_in_screen);
  594. work_area_insets->OnKeyboardAppearanceChanged(state);
  595. }
  596. ShelfLockingManager* Shelf::GetShelfLockingManagerForTesting() {
  597. return &shelf_locking_manager_;
  598. }
  599. ShelfView* Shelf::GetShelfViewForTesting() {
  600. return shelf_widget_->shelf_view_for_testing();
  601. }
  602. metrics_util::ReportCallback Shelf::GetHotseatTransitionReportCallback(
  603. HotseatState target_state) {
  604. return hotseat_transition_metrics_reporter_->GetReportCallback(target_state);
  605. }
  606. metrics_util::ReportCallback Shelf::GetTranslucentBackgroundReportCallback(
  607. HotseatState target_state) {
  608. return translucent_background_metrics_reporter_->GetReportCallback(
  609. target_state);
  610. }
  611. metrics_util::ReportCallback Shelf::GetNavigationWidgetAnimationReportCallback(
  612. HotseatState target_hotseat_state) {
  613. return navigation_widget_metrics_reporter_->GetReportCallback(
  614. target_hotseat_state);
  615. }
  616. void Shelf::WillDeleteShelfLayoutManager() {
  617. // Clear event handlers that might forward events to the destroyed instance.
  618. auto_hide_event_handler_.reset();
  619. auto_dim_event_handler_.reset();
  620. navigation_widget_metrics_reporter_.reset();
  621. DCHECK(shelf_layout_manager_);
  622. shelf_layout_manager_->RemoveObserver(this);
  623. shelf_layout_manager_ = nullptr;
  624. }
  625. void Shelf::WillChangeVisibilityState(ShelfVisibilityState new_state) {
  626. for (auto& observer : observers_)
  627. observer.WillChangeVisibilityState(new_state);
  628. if (new_state != SHELF_AUTO_HIDE) {
  629. auto_hide_event_handler_.reset();
  630. } else if (!auto_hide_event_handler_) {
  631. auto_hide_event_handler_ = std::make_unique<AutoHideEventHandler>(this);
  632. }
  633. if (!auto_dim_event_handler_ && switches::IsUsingShelfAutoDim()) {
  634. auto_dim_event_handler_ = std::make_unique<AutoDimEventHandler>(this);
  635. }
  636. }
  637. void Shelf::OnAutoHideStateChanged(ShelfAutoHideState new_state) {
  638. for (auto& observer : observers_)
  639. observer.OnAutoHideStateChanged(new_state);
  640. }
  641. void Shelf::OnBackgroundUpdated(ShelfBackgroundType background_type,
  642. AnimationChangeType change_type) {
  643. if (background_type == GetBackgroundType())
  644. return;
  645. // Shelf should undim when transitioning to show app list.
  646. if (auto_dim_event_handler_ && IsAppListBackground(background_type))
  647. UndimShelf();
  648. for (auto& observer : observers_)
  649. observer.OnBackgroundTypeChanged(background_type, change_type);
  650. }
  651. void Shelf::OnHotseatStateChanged(HotseatState old_state,
  652. HotseatState new_state) {
  653. for (auto& observer : observers_)
  654. observer.OnHotseatStateChanged(old_state, new_state);
  655. }
  656. void Shelf::OnWorkAreaInsetsChanged() {
  657. for (auto& observer : observers_)
  658. observer.OnShelfWorkAreaInsetsChanged();
  659. }
  660. void Shelf::DimShelf() {
  661. auto_dim_event_handler_->DimShelf();
  662. }
  663. void Shelf::UndimShelf() {
  664. auto_dim_event_handler_->UndimShelf();
  665. }
  666. bool Shelf::HasDimShelfTimer() {
  667. return auto_dim_event_handler_->HasDimShelfTimer();
  668. }
  669. WorkAreaInsets* Shelf::GetWorkAreaInsets() const {
  670. const aura::Window* window = GetWindow();
  671. DCHECK(window);
  672. return WorkAreaInsets::ForWindow(window->GetRootWindow());
  673. }
  674. } // namespace ash