123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ash/public/cpp/autotest_private_api_utils.h"
- #include "ash/app_list/app_list_controller_impl.h"
- #include "ash/app_list/app_list_presenter_impl.h"
- #include "ash/frame/non_client_frame_view_ash.h"
- #include "ash/shell.h"
- #include "ash/wm/mru_window_tracker.h"
- #include "ash/wm/tablet_mode/scoped_skip_user_session_blocked_check.h"
- #include "base/bind.h"
- #include "base/callback_helpers.h"
- #include "base/scoped_observation.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "ui/compositor/layer.h"
- #include "ui/compositor/layer_animation_observer.h"
- #include "ui/compositor/layer_animator.h"
- namespace ash {
- namespace {
- class HomeLauncherStateWaiter {
- public:
- HomeLauncherStateWaiter(bool target_shown, base::OnceClosure closure)
- : target_shown_(target_shown), closure_(std::move(closure)) {
- Shell::Get()
- ->app_list_controller()
- ->SetHomeLauncherAnimationCallbackForTesting(base::BindRepeating(
- &HomeLauncherStateWaiter::OnHomeLauncherAnimationCompleted,
- base::Unretained(this)));
- }
- HomeLauncherStateWaiter(const HomeLauncherStateWaiter&) = delete;
- HomeLauncherStateWaiter& operator=(const HomeLauncherStateWaiter&) = delete;
- ~HomeLauncherStateWaiter() {
- Shell::Get()
- ->app_list_controller()
- ->SetHomeLauncherAnimationCallbackForTesting(base::NullCallback());
- }
- private:
- // Passed to AppListControllerImpl as a callback to run when home launcher
- // transition animation is complete.
- void OnHomeLauncherAnimationCompleted(bool shown) {
- if (shown == target_shown_) {
- std::move(closure_).Run();
- delete this;
- }
- }
- bool target_shown_;
- base::OnceClosure closure_;
- };
- // A waiter that waits until the animation ended with the target state, and
- // execute the callback. This self destruction upon completion.
- class LauncherStateWaiter {
- public:
- LauncherStateWaiter(ash::AppListViewState state, base::OnceClosure closure)
- : target_state_(state), closure_(std::move(closure)) {
- Shell::Get()
- ->app_list_controller()
- ->SetStateTransitionAnimationCallbackForTesting(base::BindRepeating(
- &LauncherStateWaiter::OnStateChanged, base::Unretained(this)));
- }
- LauncherStateWaiter(const LauncherStateWaiter&) = delete;
- LauncherStateWaiter& operator=(const LauncherStateWaiter&) = delete;
- ~LauncherStateWaiter() {
- Shell::Get()
- ->app_list_controller()
- ->SetStateTransitionAnimationCallbackForTesting(base::NullCallback());
- }
- void OnStateChanged(ash::AppListViewState state) {
- if (target_state_ == state) {
- std::move(closure_).Run();
- delete this;
- }
- }
- private:
- ash::AppListViewState target_state_;
- base::OnceClosure closure_;
- };
- class LauncherAnimationWaiter : public ui::LayerAnimationObserver {
- public:
- LauncherAnimationWaiter(AppListView* view, base::OnceClosure closure)
- : closure_(std::move(closure)) {
- observation_.Observe(view->GetWidget()->GetLayer()->GetAnimator());
- }
- ~LauncherAnimationWaiter() override = default;
- LauncherAnimationWaiter(const LauncherAnimationWaiter&) = delete;
- LauncherAnimationWaiter& operator=(const LauncherAnimationWaiter&) = delete;
- private:
- // ui::LayerAnimationObserver:
- void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override {
- std::move(closure_).Run();
- delete this;
- }
- void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override {
- OnLayerAnimationEnded(sequence);
- }
- void OnLayerAnimationScheduled(
- ui::LayerAnimationSequence* sequence) override {}
- base::OnceClosure closure_;
- base::ScopedObservation<ui::LayerAnimator, ui::LayerAnimationObserver>
- observation_{this};
- };
- bool WaitForHomeLauncherState(bool target_visible, base::OnceClosure closure) {
- if (Shell::Get()->app_list_controller()->IsVisible(
- /*display_id=*/absl::nullopt) == target_visible) {
- std::move(closure).Run();
- return true;
- }
- new HomeLauncherStateWaiter(target_visible, std::move(closure));
- return false;
- }
- bool WaitForLauncherAnimation(base::OnceClosure closure) {
- auto* app_list_view =
- Shell::Get()->app_list_controller()->fullscreen_presenter()->GetView();
- if (!app_list_view) {
- std::move(closure).Run();
- return true;
- }
- bool animating =
- app_list_view->GetWidget()->GetLayer()->GetAnimator()->is_animating();
- if (!animating) {
- std::move(closure).Run();
- return true;
- }
- new LauncherAnimationWaiter(app_list_view, std::move(closure));
- return false;
- }
- } // namespace
- std::vector<aura::Window*> GetAppWindowList() {
- ScopedSkipUserSessionBlockedCheck skip_session_blocked;
- return Shell::Get()->mru_window_tracker()->BuildAppWindowList(kAllDesks);
- }
- bool WaitForLauncherState(AppListViewState target_state,
- base::OnceClosure closure) {
- const bool in_tablet_mode =
- Shell::Get()->tablet_mode_controller()->InTabletMode();
- if (in_tablet_mode) {
- // App-list can't enter kPeeking or kHalf state in tablet mode. Thus
- // |target_state| should be either kClosed, kFullscreenAllApps or
- // kFullscreenSearch.
- DCHECK(target_state == AppListViewState::kClosed ||
- target_state == AppListViewState::kFullscreenAllApps ||
- target_state == AppListViewState::kFullscreenSearch);
- }
- // In the tablet mode, home launcher visibility state needs special handling,
- // as app list view visibility does not match home launcher visibility. The
- // app list view is always visible, but the home launcher may be obscured by
- // app windows. The waiter interprets waits for kClosed state as waits
- // "home launcher not visible" state - note that the app list view
- // is actually expected to be in a visible state.
- AppListViewState effective_target_state =
- in_tablet_mode && target_state == AppListViewState::kClosed
- ? AppListViewState::kFullscreenAllApps
- : target_state;
- absl::optional<bool> target_home_launcher_visibility;
- if (in_tablet_mode)
- target_home_launcher_visibility = target_state != AppListViewState::kClosed;
- // Don't wait if the launcher is already in the target state and not
- // animating.
- auto* app_list_view =
- Shell::Get()->app_list_controller()->fullscreen_presenter()->GetView();
- bool animating =
- app_list_view &&
- app_list_view->GetWidget()->GetLayer()->GetAnimator()->is_animating();
- bool at_target_state =
- (!app_list_view && effective_target_state == AppListViewState::kClosed) ||
- (app_list_view &&
- app_list_view->app_list_state() == effective_target_state);
- if (at_target_state && !animating) {
- // In tablet mode, ensure that the home launcher is in the expected state.
- if (target_home_launcher_visibility.has_value()) {
- return WaitForHomeLauncherState(*target_home_launcher_visibility,
- std::move(closure));
- }
- std::move(closure).Run();
- return true;
- }
- // In tablet mode, ensure that the home launcher is in the expected state.
- base::OnceClosure callback =
- target_home_launcher_visibility.has_value()
- ? base::BindOnce(base::IgnoreResult(&WaitForHomeLauncherState),
- *target_home_launcher_visibility, std::move(closure))
- : std::move(closure);
- if (at_target_state)
- return WaitForLauncherAnimation(std::move(callback));
- new LauncherStateWaiter(
- target_state,
- base::BindOnce(base::IgnoreResult(&WaitForLauncherAnimation),
- std::move(callback)));
- return false;
- }
- } // namespace ash
|