Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(108)

Side by Side Diff: ash/wm/workspace/backdrop_controller.cc

Issue 2884623002: Refactor backdrop (Closed)
Patch Set: . Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ash/wm/maximize_mode/workspace_backdrop_delegate.h" 5 #include "ash/wm/workspace/backdrop_controller.h"
6 6
7 #include "ash/accessibility_delegate.h"
7 #include "ash/public/cpp/shell_window_ids.h" 8 #include "ash/public/cpp/shell_window_ids.h"
8 #include "ash/root_window_controller.h" 9 #include "ash/root_window_controller.h"
9 #include "ash/wm/workspace/workspace_layout_manager_backdrop_delegate.h" 10 #include "ash/shared/app_types.h"
11 #include "ash/shell.h"
12 #include "ash/system/tray/system_tray_notifier.h"
13 #include "ash/wm/window_util.h"
14 #include "ash/wm/workspace/backdrop_delegate.h"
10 #include "ash/wm_window.h" 15 #include "ash/wm_window.h"
11 #include "base/auto_reset.h" 16 #include "base/auto_reset.h"
17 #include "chromeos/audio/chromeos_sounds.h"
18 #include "ui/aura/client/aura_constants.h"
12 #include "ui/compositor/layer.h" 19 #include "ui/compositor/layer.h"
13 #include "ui/compositor/scoped_layer_animation_settings.h" 20 #include "ui/compositor/scoped_layer_animation_settings.h"
14 #include "ui/views/background.h"
15 #include "ui/views/widget/widget.h" 21 #include "ui/views/widget/widget.h"
16 #include "ui/wm/core/window_animations.h" 22 #include "ui/wm/core/window_animations.h"
17 #include "ui/wm/core/window_util.h" 23 #include "ui/wm/core/window_util.h"
18 24
19 namespace ash { 25 namespace ash {
20 namespace { 26 namespace {
21 27
22 // The opacity of the backdrop. 28 class BackdropEventHandler : public ui::EventHandler {
23 const float kBackdropOpacity = 1.0f; 29 public:
30 BackdropEventHandler() = default;
31 ~BackdropEventHandler() override = default;
32
33 // ui::EventHandler:
34 void OnEvent(ui::Event* event) override {
35 // If the event is targeted at the backdrop, it means the user has made an
36 // interaction that is outside the window's bounds and we want to capture
37 // it (usually when in spoken feedback mode). Handle the event (to prevent
38 // behind-windows from receiving it) and play an earcon to notify the user.
39 if (event->IsLocatedEvent()) {
40 switch (event->type()) {
41 case ui::ET_MOUSE_PRESSED:
42 case ui::ET_MOUSEWHEEL:
43 case ui::ET_TOUCH_PRESSED:
44 case ui::ET_POINTER_DOWN:
45 case ui::ET_POINTER_WHEEL_CHANGED:
46 case ui::ET_GESTURE_BEGIN:
47 case ui::ET_SCROLL:
48 case ui::ET_SCROLL_FLING_START:
49 Shell::Get()->accessibility_delegate()->PlayEarcon(
50 chromeos::SOUND_VOLUME_ADJUST);
51 break;
52 default:
53 break;
54 }
55 event->SetHandled();
56 }
57 }
58
59 private:
60 DISALLOW_COPY_AND_ASSIGN(BackdropEventHandler);
61 };
24 62
25 } // namespace 63 } // namespace
26 64
27 WorkspaceBackdropDelegate::WorkspaceBackdropDelegate(WmWindow* container) 65 BackdropController::BackdropController(WmWindow* container)
28 : container_(container), in_restacking_(false) { 66 : container_(container), in_restacking_(false) {
29 background_ = new views::Widget; 67 DCHECK(container_);
68 Shell::Get()->AddShellObserver(this);
69 Shell::Get()->system_tray_notifier()->AddAccessibilityObserver(this);
70 }
71
72 BackdropController::~BackdropController() {
73 Shell::Get()->system_tray_notifier()->RemoveAccessibilityObserver(this);
74 Shell::Get()->RemoveShellObserver(this);
75 // TODO: animations won't work right with mus: http://crbug.com/548396.
76 Hide();
77 }
78
79 void BackdropController::OnWindowAddedToLayout(aura::Window* child) {
80 UpdateBackdrop();
81 }
82
83 void BackdropController::OnWindowRemovedFromLayout(aura::Window* child) {
84 UpdateBackdrop();
85 }
86
87 void BackdropController::OnChildWindowVisibilityChanged(aura::Window* child,
88 bool visible) {
89 UpdateBackdrop();
90 }
91
92 void BackdropController::OnWindowStackingChanged(aura::Window* window) {
93 UpdateBackdrop();
94 }
95
96 void BackdropController::OnPostWindowStateTypeChange(
97 wm::WindowState* window_state,
98 wm::WindowStateType old_type) {
99 UpdateBackdrop();
100 }
101
102 void BackdropController::SetBackdropDelegate(
103 std::unique_ptr<BackdropDelegate> delegate) {
104 delegate_ = std::move(delegate);
105 UpdateBackdrop();
106 }
107
108 void BackdropController::UpdateBackdrop() {
109 // Avoid recursive calls.
110 if (in_restacking_ || force_hidden_)
111 return;
112
113 aura::Window* window = GetTopmostWindowWithBackdrop();
114 if (!window) {
115 // Hide backdrop since no suitable window was found.
116 Hide();
117 return;
118 }
119 // We are changing the order of windows which will cause recursion.
120 base::AutoReset<bool> lock(&in_restacking_, true);
121 EnsureBackdropWidget();
122 UpdateAccessibilityMode();
123
124 if (window == backdrop_window_ && backdrop_->IsVisible())
125 return;
126 if (window->GetRootWindow() != backdrop_window_->GetRootWindow())
127 return;
128
129 if (!backdrop_->IsVisible())
130 Show();
131
132 // Since the backdrop needs to be immediately behind the window and the
133 // stacking functions only guarantee a "it's above or below", we need
134 // to re-arrange the two windows twice.
135 container_->aura_window()->StackChildAbove(backdrop_window_, window);
136 container_->aura_window()->StackChildAbove(window, backdrop_window_);
137 }
138
139 void BackdropController::OnOverviewModeStarting() {
140 force_hidden_ = true;
141 Hide();
142 }
143
144 void BackdropController::OnOverviewModeEnded() {
145 force_hidden_ = false;
146 UpdateBackdrop();
147 }
148
149 void BackdropController::OnAccessibilityModeChanged(
150 AccessibilityNotificationVisibility notify) {
151 UpdateBackdrop();
152 }
153
154 void BackdropController::EnsureBackdropWidget() {
155 if (backdrop_)
156 return;
157
158 backdrop_ = new views::Widget;
30 views::Widget::InitParams params( 159 views::Widget::InitParams params(
31 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); 160 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
32 params.bounds = container_->GetBoundsInScreen(); 161 params.bounds = container_->GetBoundsInScreen();
33 params.layer_type = ui::LAYER_SOLID_COLOR; 162 params.layer_type = ui::LAYER_SOLID_COLOR;
34 params.name = "WorkspaceBackdropDelegate"; 163 params.name = "WorkspaceBackdropDelegate";
35 // To disallow the MRU list from picking this window up it should not be 164 // To disallow the MRU list from picking this window up it should not be
36 // activateable. 165 // activateable.
37 params.activatable = views::Widget::InitParams::ACTIVATABLE_NO; 166 params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
38 DCHECK_NE(kShellWindowId_Invalid, container_->aura_window()->id()); 167 DCHECK_NE(kShellWindowId_Invalid, container_->aura_window()->id());
39 container_->GetRootWindowController()->ConfigureWidgetInitParamsForContainer( 168 container_->GetRootWindowController()->ConfigureWidgetInitParamsForContainer(
40 background_, container_->aura_window()->id(), &params); 169 backdrop_, container_->aura_window()->id(), &params);
41 background_->Init(params); 170 backdrop_->Init(params);
42 background_window_ = WmWindow::Get(background_->GetNativeWindow()); 171 backdrop_window_ = backdrop_->GetNativeWindow();
43 // Do not use the animation system. We don't want the bounds animation and 172 backdrop_window_->SetName("Backdrop");
44 // opacity needs to get set to |kBackdropOpacity|. 173 ::wm::SetWindowVisibilityAnimationType(
45 background_window_->SetVisibilityAnimationTransition(::wm::ANIMATE_NONE); 174 backdrop_window_, ::wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
46 background_window_->GetLayer()->SetColor(SK_ColorBLACK); 175 backdrop_window_->layer()->SetColor(SK_ColorBLACK);
47 // Make sure that the layer covers visibly everything - including the shelf. 176 }
48 background_window_->GetLayer()->SetBounds(params.bounds); 177
49 DCHECK(background_window_->GetBounds() == params.bounds); 178 void BackdropController::UpdateAccessibilityMode() {
50 Show(); 179 if (!backdrop_)
51 RestackBackdrop(); 180 return;
52 } 181
53 182 bool enabled =
54 WorkspaceBackdropDelegate::~WorkspaceBackdropDelegate() { 183 Shell::Get()->accessibility_delegate()->IsSpokenFeedbackEnabled();
55 // TODO: animations won't work right with mus: http://crbug.com/548396. 184 if (enabled) {
56 ::wm::ScopedHidingAnimationSettings hiding_settings( 185 if (!backdrop_event_handler_) {
57 background_->GetNativeView()); 186 backdrop_event_handler_ = base::MakeUnique<BackdropEventHandler>();
58 background_->Close(); 187 original_event_handler_ =
59 background_window_->GetLayer()->SetOpacity(0.0f); 188 backdrop_window_->SetTargetHandler(backdrop_event_handler_.get());
60 } 189 }
61 190 } else if (backdrop_event_handler_) {
62 void WorkspaceBackdropDelegate::OnWindowAddedToLayout(WmWindow* child) { 191 backdrop_window_->SetTargetHandler(original_event_handler_);
63 RestackBackdrop(); 192 backdrop_event_handler_.reset();
64 } 193 }
65 194 }
66 void WorkspaceBackdropDelegate::OnWindowRemovedFromLayout(WmWindow* child) { 195
67 RestackBackdrop(); 196 aura::Window* BackdropController::GetTopmostWindowWithBackdrop() {
68 } 197 // ARC app should always have a backdrop when spoken feedback is enabled.
69 198 if (Shell::Get()->accessibility_delegate()->IsSpokenFeedbackEnabled()) {
70 void WorkspaceBackdropDelegate::OnChildWindowVisibilityChanged(WmWindow* child, 199 aura::Window* active_window = wm::GetActiveWindow();
71 bool visible) { 200 if (active_window && active_window->parent() == container_->aura_window() &&
72 RestackBackdrop(); 201 active_window->GetProperty(aura::client::kAppType) ==
73 } 202 static_cast<int>(ash::AppType::ARC_APP)) {
James Cook 2017/05/16 15:12:14 nit: ash:: not needed
oshima 2017/05/17 07:44:34 Done.
74 203 return active_window;
75 void WorkspaceBackdropDelegate::OnWindowStackingChanged(WmWindow* window) { 204 }
76 RestackBackdrop(); 205 }
77 } 206
78
79 void WorkspaceBackdropDelegate::OnPostWindowStateTypeChange(
80 wm::WindowState* window_state,
81 wm::WindowStateType old_type) {
82 RestackBackdrop();
83 }
84
85 void WorkspaceBackdropDelegate::RestackBackdrop() {
86 // Avoid recursive calls.
87 if (in_restacking_)
88 return;
89
90 WmWindow* window = GetCurrentTopWindow();
91 if (!window) {
92 // Hide backdrop since no suitable window was found.
93 background_->Hide();
94 return;
95 }
96 if (window == background_window_ && background_->IsVisible())
97 return;
98 if (window->GetRootWindow() != background_window_->GetRootWindow())
99 return;
100 // We are changing the order of windows which will cause recursion.
101 base::AutoReset<bool> lock(&in_restacking_, true);
102 if (!background_->IsVisible())
103 Show();
104 // Since the backdrop needs to be immediately behind the window and the
105 // stacking functions only guarantee a "it's above or below", we need
106 // to re-arrange the two windows twice.
107 container_->StackChildAbove(background_window_, window);
108 container_->StackChildAbove(window, background_window_);
109 }
110
111 WmWindow* WorkspaceBackdropDelegate::GetCurrentTopWindow() {
112 const WmWindow::Windows windows = container_->GetChildren(); 207 const WmWindow::Windows windows = container_->GetChildren();
113 for (auto window_iter = windows.rbegin(); window_iter != windows.rend(); 208 for (auto window_iter = windows.rbegin(); window_iter != windows.rend();
114 ++window_iter) { 209 ++window_iter) {
115 WmWindow* window = *window_iter; 210 WmWindow* window = *window_iter;
116 if (window->GetTargetVisibility() && 211 if (window->aura_window() != backdrop_window_ &&
212 window->GetTargetVisibility() &&
117 window->GetType() == ui::wm::WINDOW_TYPE_NORMAL && 213 window->GetType() == ui::wm::WINDOW_TYPE_NORMAL &&
118 window->CanActivate()) 214 window->CanActivate() &&
119 return window; 215 WindowShouldHaveBackdrop(window->aura_window())) {
216 return window->aura_window();
217 }
120 } 218 }
121 return nullptr; 219 return nullptr;
122 } 220 }
123 221
124 void WorkspaceBackdropDelegate::Show() { 222 bool BackdropController::WindowShouldHaveBackdrop(aura::Window* window) {
125 background_window_->GetLayer()->SetOpacity(0.0f); 223 return (window->GetAllPropertyKeys().count(aura::client::kHasBackdrop) &&
James Cook 2017/05/16 15:12:14 optional: This might be easier to read as: if (wi
126 background_->Show(); 224 window->GetProperty(aura::client::kHasBackdrop)) ||
127 background_->SetFullscreen(true); 225 (delegate_ ? delegate_->HasBackdrop(window) : false);
128 ui::ScopedLayerAnimationSettings settings( 226 }
129 background_window_->GetLayer()->GetAnimator()); 227
130 background_window_->GetLayer()->SetOpacity(kBackdropOpacity); 228 void BackdropController::Show() {
229 backdrop_->Show();
230 backdrop_->SetFullscreen(true);
231 }
232
233 void BackdropController::Hide() {
234 if (!backdrop_)
235 return;
236 backdrop_->Close();
237 backdrop_ = nullptr;
238 backdrop_window_ = nullptr;
239 original_event_handler_ = nullptr;
240 backdrop_event_handler_.reset();
131 } 241 }
132 242
133 } // namespace ash 243 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698