| // Copyright 2018 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_WM_MULTI_DISPLAY_PERSISTENT_WINDOW_CONTROLLER_H_ |
| #define ASH_WM_MULTI_DISPLAY_PERSISTENT_WINDOW_CONTROLLER_H_ |
| |
| #include <unordered_map> |
| |
| #include "ash/ash_export.h" |
| #include "ash/public/cpp/session/session_observer.h" |
| #include "base/containers/flat_map.h" |
| #include "base/functional/callback.h" |
| #include "ui/aura/window_observer.h" |
| #include "ui/display/display_observer.h" |
| #include "ui/gfx/geometry/rect.h" |
| |
| namespace aura { |
| class Window; |
| } // namespace aura |
| |
| namespace ash { |
| |
| // Observes display changes and saves/restores window bounds persistently in |
| // multi-displays scenario. It will observe and restore window bounds |
| // persistently on screen rotation as well. |
| class ASH_EXPORT PersistentWindowController : public display::DisplayObserver, |
| public SessionObserver { |
| public: |
| // This class is used to track a list of windows with their restore bounds in |
| // parent. The restore bounds in parent will be empty if it does not exist. |
| // When a window is destroyed, it is removed from the list. |
| class WindowTracker : public aura::WindowObserver { |
| public: |
| WindowTracker(); |
| |
| WindowTracker(const WindowTracker&) = delete; |
| WindowTracker& operator=(const WindowTracker&) = delete; |
| |
| ~WindowTracker() override; |
| |
| const base::flat_map<aura::Window*, gfx::Rect>& window_restore_bounds_map() |
| const { |
| return window_restore_bounds_map_; |
| } |
| |
| // Adds {window, restore_bounds_in_parent} as a pair to the map. If the |
| // `window` is already tracked, it will do nothing. |
| void Add(aura::Window* window, const gfx::Rect& restore_bounds_in_parent); |
| |
| void RemoveAll(); |
| |
| // Removes `window` from the map of windows with restore bounds. |
| void Remove(aura::Window* window); |
| |
| // aura::WindowObserver: |
| void OnWindowDestroying(aura::Window* window) override; |
| |
| private: |
| base::flat_map<aura::Window*, gfx::Rect> window_restore_bounds_map_; |
| }; |
| |
| // Public so it can be used by unit tests. |
| constexpr static char kNumOfWindowsRestoredOnDisplayAdded[] = |
| "Ash.PersistentWindow.NumOfWindowsRestoredOnDisplayAdded"; |
| constexpr static char kNumOfWindowsRestoredOnScreenRotation[] = |
| "Ash.PersistentWindow.NumOfWindowsRestoredOnScreenRotation"; |
| |
| PersistentWindowController(); |
| PersistentWindowController(const PersistentWindowController&) = delete; |
| PersistentWindowController& operator=(const PersistentWindowController&) = |
| delete; |
| ~PersistentWindowController() override; |
| |
| private: |
| // display::DisplayObserver: |
| void OnWillProcessDisplayChanges() override; |
| void OnDisplayAdded(const display::Display& new_display) override; |
| void OnDisplayRemoved(const display::Display& old_display) override; |
| void OnDisplayMetricsChanged(const display::Display& display, |
| uint32_t changed_metrics) override; |
| void OnDidProcessDisplayChanges() override; |
| |
| // SessionObserver: |
| void OnFirstSessionStarted() override; |
| |
| // Called when restoring persistent window placement on display added. |
| void MaybeRestorePersistentWindowBoundsOnDisplayAdded(); |
| |
| // Called when restoring persistent window placement on screen rotation. |
| void MaybeRestorePersistentWindowBoundsOnScreenRotation(); |
| |
| // Callback binded on display added and run on display changes are processed. |
| base::OnceClosure display_added_restore_callback_; |
| |
| // Callback binded on display rotation happens and run on display changes are |
| // processed. |
| base::OnceClosure screen_rotation_restore_callback_; |
| |
| // Temporary storage that stores windows that may need persistent info |
| // stored on display removal. Cleared when display changes are processed. |
| WindowTracker need_persistent_info_windows_; |
| |
| // Tracking the screen orientation of each display before screen rotation |
| // take effect. Key is the display id, value is true if the display is in |
| // the landscape orientation, otherwise false. This is used to help restore |
| // windows' bounds on screen rotation. It is needed since the target rotation |
| // already changed even inside OnWillProcessDisplayChanges, which means the |
| // screen orientation checked there will be the updated orientation when |
| // screen rotation happens. So we get the initial screen orientation |
| // OnFirstSessionStarted and store the updated ones inside |
| // OnDidProcessDisplayChanges. |
| std::unordered_map<int64_t, bool> is_landscape_orientation_map_; |
| |
| // Register for DisplayObserver callbacks. |
| display::ScopedDisplayObserver display_observer_{this}; |
| }; |
| |
| } // namespace ash |
| |
| #endif // ASH_WM_MULTI_DISPLAY_PERSISTENT_WINDOW_CONTROLLER_H_ |