| // 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. |
| |
| #include "chrome/browser/ash/window_throttle_observer_base.h" |
| |
| #include "ash/public/cpp/shell_window_ids.h" |
| #include "components/exo/wm_helper.h" |
| #include "ui/aura/window.h" |
| #include "ui/wm/public/activation_change_observer.h" |
| |
| namespace ash { |
| namespace { |
| |
| // Returns true if the window is in the app list window container. |
| bool IsAppListWindow(const aura::Window* window) { |
| if (!window) |
| return false; |
| |
| const aura::Window* parent = window->parent(); |
| return parent && |
| parent->GetId() == ShellWindowId::kShellWindowId_AppListContainer; |
| } |
| |
| // Returns true if this window activation should be ignored (app list |
| // opening/closing), or false if it should be processed. |
| bool ShouldIgnoreWindowActivation( |
| wm::ActivationChangeObserver::ActivationReason reason, |
| aura::Window* gained_active, |
| aura::Window* lost_active) { |
| // The current active window defines whether the instance should be |
| // throttled or not i.e. if it's a native window then throttle Android, if |
| // it's an Android window then unthrottle it. |
| // |
| // However, the app list needs to be handled differently. The app list is |
| // deemed as an temporary overlay over the user's main window for browsing |
| // through or selecting an app. Consequently, if the app list is brought |
| // over a Chrome window then IsAppListWindow(gained_active) is true and this |
| // event is ignored. The instance continues to be throttled. Once the app |
| // list is closed then IsAppListWindow(lost_active) is true and the instance |
| // continues to be throttled. Similarly, if the app list is brought over an |
| // Android window, the instance continues to be unthrottled. |
| // |
| // On launching an app from the app list on Chrome OS the following events |
| // happen - |
| // |
| // - When an Android app icon is clicked the instance is unthrottled. This |
| // logic resides in |LaunchAppWithIntent| in |
| // src/chrome/browser/ash/app_list/arc/arc_app_utils.cc. |
| // |
| // - Between the time the app opens there is a narrow slice of time where |
| // this callback is triggered with |lost_active| equal to the app list |
| // window and the gained active possibly a native window. Without the check |
| // below the instance will be throttled again, further delaying the app |
| // launch. If the app was a native one then the instance was throttled |
| // anyway. |
| if (IsAppListWindow(lost_active) || IsAppListWindow(gained_active)) |
| return true; |
| return false; |
| } |
| |
| } // namespace |
| |
| WindowThrottleObserverBase::WindowThrottleObserverBase(const std::string& name) |
| : ThrottleObserver(name) {} |
| |
| void WindowThrottleObserverBase::StartObserving( |
| content::BrowserContext* context, |
| const ObserverStateChangedCallback& callback) { |
| ThrottleObserver::StartObserving(context, callback); |
| if (!exo::WMHelper::HasInstance()) // for unit testing |
| return; |
| exo::WMHelper::GetInstance()->AddActivationObserver(this); |
| } |
| |
| void WindowThrottleObserverBase::StopObserving() { |
| ThrottleObserver::StopObserving(); |
| if (!exo::WMHelper::HasInstance()) |
| return; |
| exo::WMHelper::GetInstance()->RemoveActivationObserver(this); |
| } |
| |
| void WindowThrottleObserverBase::OnWindowActivated(ActivationReason reason, |
| aura::Window* gained_active, |
| aura::Window* lost_active) { |
| if (ShouldIgnoreWindowActivation(reason, gained_active, lost_active)) |
| return; |
| SetActive(ProcessWindowActivation(reason, gained_active, lost_active)); |
| } |
| |
| } // namespace ash |