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
ash / wm / tablet_mode / tablet_mode_window_manager.h [blame]
// Copyright 2014 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_TABLET_MODE_TABLET_MODE_WINDOW_MANAGER_H_
#define ASH_WM_TABLET_MODE_TABLET_MODE_WINDOW_MANAGER_H_
#include <stdint.h>
#include <map>
#include <unordered_set>
#include <utility>
#include <vector>
#include "ash/ash_export.h"
#include "ash/public/cpp/session/session_observer.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/overview/overview_observer.h"
#include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/splitview/split_view_observer.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "ui/aura/window_observer.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/display/display_observer.h"
namespace aura {
class Window;
}
namespace ash {
class TabletModeController;
class TabletModeMultitaskMenuController;
class TabletModeToggleFullscreenEventHandler;
class TabletModeWindowState;
// A window manager which - when created - will force all windows into maximized
// mode. Exception are panels and windows which cannot be maximized.
// Windows which cannot be maximized / resized are centered with a layer placed
// behind the window so that no other windows are visible and/or obscured.
// With the destruction of the manager all windows will be restored to their
// original state.
class ASH_EXPORT TabletModeWindowManager : public aura::WindowObserver,
public display::DisplayObserver,
public OverviewObserver,
public SplitViewObserver,
public SessionObserver {
public:
// There are two reasons that we would destroy `this`.
enum class ShutdownReason {
kSystemShutdown,
kExitTabletUIMode,
};
// This should only be created or deleted by the creator
// (TabletModeController).
TabletModeWindowManager();
TabletModeWindowManager(const TabletModeWindowManager&) = delete;
TabletModeWindowManager& operator=(const TabletModeWindowManager&) = delete;
~TabletModeWindowManager() override;
TabletModeMultitaskMenuController* tablet_mode_multitask_menu_controller() {
return tablet_mode_multitask_menu_controller_.get();
}
void Init();
// Stops tracking windows and returns them to their clamshell mode state. Work
// is done here instead of the destructor because TabletModeController may
// still need this object alive during shutdown.
void Shutdown(ShutdownReason shutdown_reason);
// True if |window| is in |window_state_map_|.
bool IsTrackingWindow(aura::Window* window);
// Returns the number of maximized & tracked windows by this manager.
int GetNumberOfManagedWindows();
// Adds a window which needs to be maximized. This is used by other window
// managers for windows which needs to get tracked due to (upcoming) state
// changes.
// The call gets ignored if the window was already or should not be handled.
void AddWindow(aura::Window* window);
// Called from a window state object when it gets destroyed.
void WindowStateDestroyed(aura::Window* window);
// Tell all managing windows not to handle WM events.
void SetIgnoreWmEventsForExit();
// Stops animations on windows managed by this TabletModeWindowManager.
void StopWindowAnimations();
// OverviewObserver:
void OnOverviewModeEndingAnimationComplete(bool canceled) override;
// SplitViewObserver:
void OnSplitViewStateChanged(SplitViewController::State previous_state,
SplitViewController::State state) override;
// aura::WindowObserver:
void OnWindowDestroying(aura::Window* window) override;
void OnWindowHierarchyChanged(const HierarchyChangeParams& params) override;
void OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) override;
void OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds,
ui::PropertyChangeReason reason) override;
void OnWindowVisibilityChanged(aura::Window* window, bool visible) override;
// display::DisplayObserver:
void OnDisplayAdded(const display::Display& display) override;
void OnDisplaysRemoved(const display::Displays& removed_displays) override;
// SessionObserver:
void OnActiveUserSessionChanged(const AccountId& account_id) override;
private:
using WindowToState =
std::map<aura::Window*, raw_ptr<TabletModeWindowState, CtnExperimental>>;
using WindowAndStateTypeList =
std::vector<std::pair<aura::Window*, chromeos::WindowStateType>>;
// If |from_clamshell| is true, returns the bounds or state type that |window|
// had before tablet mode started. If |from_clamshell| is false, returns the
// current bounds or state type of |window|.
gfx::Rect GetWindowBoundsInScreen(aura::Window* window,
bool from_clamshell) const;
chromeos::WindowStateType GetWindowStateType(aura::Window* window,
bool from_clamshell) const;
// Returns the windows that are going to be carried over to split view during
// clamshell <-> tablet transition or multi-user switch transition.
std::vector<std::pair<aura::Window*, chromeos::WindowStateType>>
GetCarryOverWindowsInSplitView(bool clamshell_to_tablet) const;
// Calculates the split view divider position that will best preserve the
// bounds of the windows.
int CalculateCarryOverDividerPosition(
const WindowAndStateTypeList& windows_in_splitview,
bool clamshell_to_tablet) const;
// Maximizes all windows, except that snapped windows shall carry over to
// split view as determined by GetCarryOverWindowsInSplitView().
void ArrangeWindowsForTabletMode();
// Reverts all windows to how they were arranged before tablet mode.
// |windows_in_splitview| contains the windows that were in splitview before
// entering clamshell mode, and if clamshell split view is enabled, these
// windows will be carried over to clamshell split view. |was_in_overview|
// indicates whether overview is active before entering clamshell mode.
void ArrangeWindowsForClamshellMode(
WindowAndStateTypeList windows_in_splitview,
bool was_in_overview);
// If the given window should be handled by us, this function will add it to
// the list of known windows (remembering the initial show state).
// Note: If the given window cannot be handled by us the function will return
// immediately.
void TrackWindow(aura::Window* window,
bool entering_tablet_mode = false,
bool snap = false,
bool animate_bounds_on_attach = true);
// Removes a window from our tracking list. |was_in_overview| used when
// |destroyed| is false to help handle leaving tablet mode. If the window is
// going to be destroyed, do not restore its old previous window state object
// as it will send unnecessary window state change event.
void ForgetWindow(aura::Window* window,
bool destroyed,
bool was_in_overview = false);
// Returns true when the given window should be modified in any way by us.
bool ShouldHandleWindow(aura::Window* window);
// Add window creation observers to track creation of new windows.
void AddWindowCreationObservers();
// Remove Window creation observers.
void RemoveWindowCreationObservers();
// Change the internal state (e.g. observers) when the display configuration
// changes.
void DisplayConfigurationChanged();
// Returns true when the |window| is a container window.
bool IsContainerWindow(aura::Window* window);
// Every window which got touched by our window manager gets added here.
WindowToState window_state_map_;
// All container windows which have to be tracked.
std::unordered_set<raw_ptr<aura::Window, CtnExperimental>>
observed_container_windows_;
// Windows added to the container, but not yet shown or tracked. They will be
// attempted to be tracked when the window is shown.
std::unordered_set<raw_ptr<aura::Window, CtnExperimental>> windows_to_track_;
// All accounts that have been active at least once since tablet mode started.
base::flat_set<AccountId> accounts_since_entering_tablet_;
std::unique_ptr<TabletModeToggleFullscreenEventHandler> event_handler_;
// Handles gestures that may show or hide the multitask menu.
std::unique_ptr<TabletModeMultitaskMenuController>
tablet_mode_multitask_menu_controller_;
std::optional<display::ScopedDisplayObserver> display_observer_;
// True when tablet mode is about to end.
bool is_exiting_ = false;
base::WeakPtrFactory<TabletModeWindowManager> weak_ptr_factory_{this};
};
} // namespace ash
#endif // ASH_WM_TABLET_MODE_TABLET_MODE_WINDOW_MANAGER_H_