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

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

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

Powered by Google App Engine
This is Rietveld 408576698