Commit ed257cfb authored by Ahmed Fakhry's avatar Ahmed Fakhry Committed by Commit Bot

Improve the backdrop behavior and code

- The backdrop used to show immediately even if the
  window-needing-it is still animating, making the animation
  look poor.
- There multiple recursive calls to UpdateBackdrop() constantly
  all the time, many of them are not necessary, and can be handled
  only by laying out the backdrop if needed.
- Even the browser's status bubble used to cause multiple called
  to UpdateBackdrop() as the user moves their mouse hovering over
  links, which causes the status bubble to be created, removed,
  and have visibility changes.
- The backdrop window itself causes calls to UpdateBackdrop as it
  gets shown and hidden.
- The backdrops weren't showing in the desks mini_views (a
  regression caused by me).
- WorkspaceLayoutManager and Desk were both updating the backdrops
  for the same event.

This CL fixes the above issues.

BUG=1031789
TEST=Manually, all backdrop tests should pass.

Change-Id: I5e25705ae50abdf1cf69b63b01f762044587f600
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1974593
Commit-Queue: Ahmed Fakhry <afakhry@chromium.org>
Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Reviewed-by: default avatarPeter Boström <pbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#730046}
parent 7f9d859a
...@@ -781,14 +781,8 @@ void ShelfWidget::OnGestureEvent(ui::GestureEvent* event) { ...@@ -781,14 +781,8 @@ void ShelfWidget::OnGestureEvent(ui::GestureEvent* event) {
} }
void ShelfWidget::OnAccessibilityStatusChanged() { void ShelfWidget::OnAccessibilityStatusChanged() {
// Only handles when the spoken feedback is disabled. is_hotseat_forced_to_show_ =
if (Shell::Get()->accessibility_controller()->spoken_feedback_enabled()) Shell::Get()->accessibility_controller()->spoken_feedback_enabled();
return;
if (!is_hotseat_forced_to_show_)
return;
is_hotseat_forced_to_show_ = false;
shelf_layout_manager_->UpdateVisibilityState(); shelf_layout_manager_->UpdateVisibilityState();
} }
......
...@@ -183,8 +183,9 @@ void Desk::AddWindowToDesk(aura::Window* window) { ...@@ -183,8 +183,9 @@ void Desk::AddWindowToDesk(aura::Window* window) {
windows_.push_back(window); windows_.push_back(window);
// No need to refresh the mini_views if the destroyed window doesn't show up // No need to refresh the mini_views if the destroyed window doesn't show up
// there in the first place. // there in the first place.
// The WorkspaceLayoutManager updates the backdrop for us.
if (!window->GetProperty(kHideInDeskMiniViewKey)) if (!window->GetProperty(kHideInDeskMiniViewKey))
NotifyContentChanged(); NotifyContentChanged(/*update_backdrops=*/false);
} }
void Desk::RemoveWindowFromDesk(aura::Window* window) { void Desk::RemoveWindowFromDesk(aura::Window* window) {
...@@ -192,8 +193,9 @@ void Desk::RemoveWindowFromDesk(aura::Window* window) { ...@@ -192,8 +193,9 @@ void Desk::RemoveWindowFromDesk(aura::Window* window) {
base::Erase(windows_, window); base::Erase(windows_, window);
// No need to refresh the mini_views if the destroyed window doesn't show up // No need to refresh the mini_views if the destroyed window doesn't show up
// there in the first place. // there in the first place.
// The WorkspaceLayoutManager updates the backdrop for us.
if (!window->GetProperty(kHideInDeskMiniViewKey)) if (!window->GetProperty(kHideInDeskMiniViewKey))
NotifyContentChanged(); NotifyContentChanged(/*update_backdrops=*/false);
} }
base::AutoReset<bool> Desk::GetScopedNotifyContentChangedDisabler() { base::AutoReset<bool> Desk::GetScopedNotifyContentChangedDisabler() {
...@@ -278,8 +280,8 @@ void Desk::MoveWindowsToDesk(Desk* target_desk) { ...@@ -278,8 +280,8 @@ void Desk::MoveWindowsToDesk(Desk* target_desk) {
} }
} }
NotifyContentChanged(); NotifyContentChanged(/*update_backdrops=*/true);
target_desk->NotifyContentChanged(); target_desk->NotifyContentChanged(/*update_backdrops=*/true);
} }
void Desk::MoveWindowToDesk(aura::Window* window, Desk* target_desk) { void Desk::MoveWindowToDesk(aura::Window* window, Desk* target_desk) {
...@@ -314,8 +316,8 @@ void Desk::MoveWindowToDesk(aura::Window* window, Desk* target_desk) { ...@@ -314,8 +316,8 @@ void Desk::MoveWindowToDesk(aura::Window* window, Desk* target_desk) {
window_state->Unminimize(); window_state->Unminimize();
} }
NotifyContentChanged(); NotifyContentChanged(/*update_backdrops=*/true);
target_desk->NotifyContentChanged(); target_desk->NotifyContentChanged(/*update_backdrops=*/true);
} }
aura::Window* Desk::GetDeskContainerForRoot(aura::Window* root) const { aura::Window* Desk::GetDeskContainerForRoot(aura::Window* root) const {
...@@ -324,13 +326,15 @@ aura::Window* Desk::GetDeskContainerForRoot(aura::Window* root) const { ...@@ -324,13 +326,15 @@ aura::Window* Desk::GetDeskContainerForRoot(aura::Window* root) const {
return root->GetChildById(container_id_); return root->GetChildById(container_id_);
} }
void Desk::NotifyContentChanged() { void Desk::NotifyContentChanged(bool update_backdrops) {
if (!should_notify_content_changed_) if (!should_notify_content_changed_)
return; return;
// Update the backdrop availability and visibility first before notifying // If requested, update the backdrop availability and visibility first before
// observers. // notifying observers, so that the mini_views update *after* the backdrops
UpdateDeskBackdrops(); // do.
if (update_backdrops)
UpdateDeskBackdrops();
for (auto& observer : observers_) for (auto& observer : observers_)
observer.OnContentChanged(); observer.OnContentChanged();
......
...@@ -88,10 +88,18 @@ class ASH_EXPORT Desk { ...@@ -88,10 +88,18 @@ class ASH_EXPORT Desk {
aura::Window* GetDeskContainerForRoot(aura::Window* root) const; aura::Window* GetDeskContainerForRoot(aura::Window* root) const;
void NotifyContentChanged(); // Notifies observers that the desk's contents (list of application windows on
// the desk) have changed.
// Updates the backdrop availability and visibility on the containers (on all // If |update_backdrops| is true, the backdrops of all containers associated
// roots) associated with this desk. // with this desk will be updated (even if overview is active).
// This is *only* needed if the WorkspaceLayoutManager won't take care of this
// for us in desk-modifying operations that happen within overview, such as
// removing desks (and move its windows out) or dragging a window and dropping
// in another desk.
void NotifyContentChanged(bool update_backdrops);
// Update (even if overview is active) the backdrop availability and
// visibility on the containers (on all roots) associated with this desk.
void UpdateDeskBackdrops(); void UpdateDeskBackdrops();
private: private:
......
...@@ -803,7 +803,7 @@ void DesksController::RemoveDeskInternal(const Desk* desk, ...@@ -803,7 +803,7 @@ void DesksController::RemoveDeskInternal(const Desk* desk,
// if windows from the removed desk moved to it. // if windows from the removed desk moved to it.
DCHECK(active_desk_->should_notify_content_changed()); DCHECK(active_desk_->should_notify_content_changed());
if (!removed_desk_windows.empty()) if (!removed_desk_windows.empty())
active_desk_->NotifyContentChanged(); active_desk_->NotifyContentChanged(/*force_update_backdrops=*/true);
for (auto& observer : observers_) for (auto& observer : observers_)
observer.OnDeskRemoved(removed_desk.get()); observer.OnDeskRemoved(removed_desk.get());
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "ash/accessibility/accessibility_controller_impl.h" #include "ash/accessibility/accessibility_controller_impl.h"
#include "ash/accessibility/accessibility_delegate.h" #include "ash/accessibility/accessibility_delegate.h"
#include "ash/animation/animation_change_type.h"
#include "ash/public/cpp/app_types.h" #include "ash/public/cpp/app_types.h"
#include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/shell_window_ids.h"
#include "ash/public/cpp/window_animation_types.h" #include "ash/public/cpp/window_animation_types.h"
...@@ -23,9 +24,12 @@ ...@@ -23,9 +24,12 @@
#include "ash/wm/window_state.h" #include "ash/wm/window_state.h"
#include "ash/wm/window_util.h" #include "ash/wm/window_util.h"
#include "base/auto_reset.h" #include "base/auto_reset.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/audio/chromeos_sounds.h" #include "chromeos/audio/chromeos_sounds.h"
#include "ui/aura/client/aura_constants.h" #include "ui/aura/client/aura_constants.h"
#include "ui/compositor/layer.h" #include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_element.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/views/widget/widget.h" #include "ui/views/widget/widget.h"
#include "ui/wm/core/window_util.h" #include "ui/wm/core/window_util.h"
...@@ -46,6 +50,9 @@ SkColor GetBackdropColorByMode(BackdropWindowMode mode) { ...@@ -46,6 +50,9 @@ SkColor GetBackdropColorByMode(BackdropWindowMode mode) {
return SK_ColorBLACK; return SK_ColorBLACK;
} }
// -----------------------------------------------------------------------------
// BackdropEventHandler:
class BackdropEventHandler : public ui::EventHandler { class BackdropEventHandler : public ui::EventHandler {
public: public:
BackdropEventHandler() = default; BackdropEventHandler() = default;
...@@ -79,6 +86,45 @@ class BackdropEventHandler : public ui::EventHandler { ...@@ -79,6 +86,45 @@ class BackdropEventHandler : public ui::EventHandler {
DISALLOW_COPY_AND_ASSIGN(BackdropEventHandler); DISALLOW_COPY_AND_ASSIGN(BackdropEventHandler);
}; };
// -----------------------------------------------------------------------------
// ScopedWindowVisibilityAnimationTypeResetter:
// Sets |window|'s visibility animation type to |new_type| and resets it back to
// WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT when it goes out of scope.
class ScopedWindowVisibilityAnimationTypeResetter {
public:
ScopedWindowVisibilityAnimationTypeResetter(aura::Window* window,
int new_type)
: window_(window) {
DCHECK(window);
if (::wm::GetWindowVisibilityAnimationType(window) == new_type) {
// Clear so as not to do anything when we go out of scope.
window_ = nullptr;
return;
}
::wm::SetWindowVisibilityAnimationType(window_, new_type);
}
~ScopedWindowVisibilityAnimationTypeResetter() {
if (window_) {
::wm::SetWindowVisibilityAnimationType(
window_, ::wm::WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT);
}
}
ScopedWindowVisibilityAnimationTypeResetter(
const ScopedWindowVisibilityAnimationTypeResetter&) = delete;
ScopedWindowVisibilityAnimationTypeResetter& operator=(
const ScopedWindowVisibilityAnimationTypeResetter&) = delete;
private:
aura::Window* window_;
};
// -----------------------------------------------------------------------------
bool InOverviewSession() { bool InOverviewSession() {
OverviewController* overview_controller = Shell::Get()->overview_controller(); OverviewController* overview_controller = Shell::Get()->overview_controller();
return overview_controller && overview_controller->InOverviewSession(); return overview_controller && overview_controller->InOverviewSession();
...@@ -121,6 +167,51 @@ aura::Window* GetBottomMostSnappedWindowForDeskContainer( ...@@ -121,6 +167,51 @@ aura::Window* GetBottomMostSnappedWindowForDeskContainer(
} // namespace } // namespace
// -----------------------------------------------------------------------------
// BackdropController::WindowAnimationWaiter:
// Observers an ongoing animation of |animating_window| and updates the backdrop
// once that animation completes.
class BackdropController::WindowAnimationWaiter
: public ui::ImplicitAnimationObserver {
public:
WindowAnimationWaiter(BackdropController* owner,
aura::Window* animating_window)
: owner_(owner), animating_window_(animating_window) {
auto* animator = animating_window_->layer()->GetAnimator();
DCHECK(animator->is_animating());
const auto original_transition_duration = animator->GetTransitionDuration();
// Don't let |settings| overwrite the existing animation's duration.
ui::ScopedLayerAnimationSettings settings{animator};
settings.SetTransitionDuration(original_transition_duration);
settings.AddObserver(this);
}
~WindowAnimationWaiter() override { StopObservingImplicitAnimations(); }
WindowAnimationWaiter(const WindowAnimationWaiter&) = delete;
WindowAnimationWaiter& operator=(const WindowAnimationWaiter&) = delete;
aura::Window* animating_window() { return animating_window_; }
// ui::ImplicitAnimationObserver:
void OnImplicitAnimationsCompleted() override {
// We keep this object alive until we update the backdrop, since we use the
// member `owner_` below. This is not necessary, since we can cache it as
// a local before we reset `window_animation_waiter_`, but this way things
// are more deterministic, just in case.
auto to_destroy = std::move(owner_->window_animation_waiter_);
DCHECK_EQ(this, to_destroy.get());
owner_->UpdateBackdrop();
}
private:
BackdropController* owner_;
aura::Window* animating_window_;
};
// -----------------------------------------------------------------------------
BackdropController::BackdropController(aura::Window* container) BackdropController::BackdropController(aura::Window* container)
: root_window_(container->GetRootWindow()), container_(container) { : root_window_(container->GetRootWindow()), container_(container) {
DCHECK(container_); DCHECK(container_);
...@@ -147,28 +238,42 @@ BackdropController::~BackdropController() { ...@@ -147,28 +238,42 @@ BackdropController::~BackdropController() {
Hide(/*destroy=*/true); Hide(/*destroy=*/true);
} }
void BackdropController::OnWindowAddedToLayout() { void BackdropController::OnWindowAddedToLayout(aura::Window* window) {
UpdateBackdrop(); if (DoesWindowCauseBackdropUpdates(window))
UpdateBackdrop();
} }
void BackdropController::OnWindowRemovedFromLayout() { void BackdropController::OnWindowRemovedFromLayout(aura::Window* window) {
UpdateBackdrop(); if (DoesWindowCauseBackdropUpdates(window))
UpdateBackdrop();
} }
void BackdropController::OnChildWindowVisibilityChanged() { void BackdropController::OnChildWindowVisibilityChanged(aura::Window* window) {
UpdateBackdrop(); if (DoesWindowCauseBackdropUpdates(window))
UpdateBackdrop();
} }
void BackdropController::OnWindowStackingChanged() { void BackdropController::OnBackdropWindowModePropertyChanged(
UpdateBackdrop(); aura::Window* window) {
if (DoesWindowCauseBackdropUpdates(window))
UpdateBackdrop();
}
void BackdropController::OnWindowStackingChanged(aura::Window* window) {
if (DoesWindowCauseBackdropUpdates(window))
UpdateBackdrop();
} }
void BackdropController::OnDisplayMetricsChanged() { void BackdropController::OnDisplayMetricsChanged() {
UpdateBackdrop(); // Display changes such as rotation, device scale factor, ... etc. don't
// affect the visibility or availability of the backdrop. They may however
// affect its bounds. So just layout.
MaybeUpdateLayout();
} }
void BackdropController::OnPostWindowStateTypeChange() { void BackdropController::OnPostWindowStateTypeChange(aura::Window* window) {
UpdateBackdrop(); if (DoesWindowCauseBackdropUpdates(window))
UpdateBackdrop();
} }
void BackdropController::OnDeskContentChanged() { void BackdropController::OnDeskContentChanged() {
...@@ -248,7 +353,7 @@ void BackdropController::OnOverviewModeEndingAnimationComplete(bool canceled) { ...@@ -248,7 +353,7 @@ void BackdropController::OnOverviewModeEndingAnimationComplete(bool canceled) {
} }
void BackdropController::OnAccessibilityStatusChanged() { void BackdropController::OnAccessibilityStatusChanged() {
UpdateBackdrop(); UpdateAccessibilityMode();
} }
void BackdropController::OnSplitViewStateChanged( void BackdropController::OnSplitViewStateChanged(
...@@ -260,7 +365,7 @@ void BackdropController::OnSplitViewStateChanged( ...@@ -260,7 +365,7 @@ void BackdropController::OnSplitViewStateChanged(
} }
void BackdropController::OnSplitViewDividerPositionChanged() { void BackdropController::OnSplitViewDividerPositionChanged() {
UpdateBackdrop(); MaybeUpdateLayout();
} }
void BackdropController::OnWallpaperPreviewStarted() { void BackdropController::OnWallpaperPreviewStarted() {
...@@ -294,39 +399,36 @@ void BackdropController::UpdateBackdropInternal() { ...@@ -294,39 +399,36 @@ void BackdropController::UpdateBackdropInternal() {
// windows which will cause recursion. // windows which will cause recursion.
base::AutoReset<bool> lock(&pause_update_, true); base::AutoReset<bool> lock(&pause_update_, true);
aura::Window* window = GetTopmostWindowWithBackdrop(); aura::Window* window = GetTopmostWindowWithBackdrop();
if (!window) {
// Destroy the backdrop since no suitable window was found. if (window == window_having_backdrop_) {
Hide(/*destroy=*/true); if (window)
Show();
return; return;
} }
EnsureBackdropWidget(window->GetProperty(kBackdropWindowMode)); window_having_backdrop_ = window;
UpdateAccessibilityMode();
if (window == backdrop_window_ && backdrop_->IsVisible()) { if (!window_having_backdrop_) {
Layout(); // Destroy the backdrop since no suitable window was found.
Hide(/*destroy=*/true);
return; return;
} }
if (window->GetRootWindow() != backdrop_window_->GetRootWindow())
return;
// Update the animation type of |backdrop_window_| based on current top most DCHECK_EQ(window_having_backdrop_->GetRootWindow(), root_window_);
// window with backdrop. DCHECK_NE(window_having_backdrop_, backdrop_window_);
SetBackdropAnimationType(WindowState::Get(window)->CanMaximize()
? WINDOW_VISIBILITY_ANIMATION_TYPE_STEP_END
: ::wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
EnsureBackdropWidget();
Show(); Show();
}
SetBackdropAnimationType(::wm::WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT); void BackdropController::EnsureBackdropWidget() {
DCHECK(window_having_backdrop_);
// Backdrop needs to be immediately behind the window. const BackdropWindowMode mode =
container_->StackChildBelow(backdrop_window_, window); window_having_backdrop_->GetProperty(kBackdropWindowMode);
} const SkColor backdrop_color = GetBackdropColorByMode(mode);
void BackdropController::EnsureBackdropWidget(BackdropWindowMode mode) {
if (backdrop_) { if (backdrop_) {
SkColor backdrop_color = GetBackdropColorByMode(mode);
if (backdrop_window_->layer()->GetTargetColor() != backdrop_color) if (backdrop_window_->layer()->GetTargetColor() != backdrop_color)
backdrop_window_->layer()->SetColor(backdrop_color); backdrop_window_->layer()->SetColor(backdrop_color);
return; return;
...@@ -344,22 +446,25 @@ void BackdropController::EnsureBackdropWidget(BackdropWindowMode mode) { ...@@ -344,22 +446,25 @@ void BackdropController::EnsureBackdropWidget(BackdropWindowMode mode) {
params.activatable = views::Widget::InitParams::ACTIVATABLE_NO; params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
DCHECK_NE(kShellWindowId_Invalid, container_->id()); DCHECK_NE(kShellWindowId_Invalid, container_->id());
params.parent = container_; params.parent = container_;
params.init_properties_container.SetProperty(kHideInOverviewKey, true);
params.init_properties_container.SetProperty(kForceVisibleInMiniViewKey,
true);
backdrop_->Init(std::move(params)); backdrop_->Init(std::move(params));
backdrop_window_ = backdrop_->GetNativeWindow(); backdrop_window_ = backdrop_->GetNativeWindow();
backdrop_window_->SetProperty(kHideInOverviewKey, true);
// The backdrop window in always on top container can be reparented without // The backdrop window in always on top container can be reparented without
// this when the window is set to fullscreen. // this when the window is set to fullscreen.
AlwaysOnTopController::SetDisallowReparent(backdrop_window_); AlwaysOnTopController::SetDisallowReparent(backdrop_window_);
backdrop_window_->layer()->SetColor(GetBackdropColorByMode(mode)); backdrop_window_->layer()->SetColor(backdrop_color);
WindowState::Get(backdrop_window_)->set_allow_set_bounds_direct(true); WindowState::Get(backdrop_window_)->set_allow_set_bounds_direct(true);
UpdateAccessibilityMode();
} }
void BackdropController::UpdateAccessibilityMode() { void BackdropController::UpdateAccessibilityMode() {
if (!backdrop_) if (!backdrop_)
return; return;
bool enabled = const bool enabled =
Shell::Get()->accessibility_controller()->spoken_feedback_enabled(); Shell::Get()->accessibility_controller()->spoken_feedback_enabled();
if (enabled) { if (enabled) {
if (!backdrop_event_handler_) { if (!backdrop_event_handler_) {
...@@ -413,12 +518,29 @@ bool BackdropController::WindowShouldHaveBackdrop(aura::Window* window) { ...@@ -413,12 +518,29 @@ bool BackdropController::WindowShouldHaveBackdrop(aura::Window* window) {
} }
void BackdropController::Show() { void BackdropController::Show() {
DCHECK(backdrop_);
DCHECK(backdrop_window_);
DCHECK(window_having_backdrop_);
if (MaybeWaitForWindowAnimation())
return;
Layout(); Layout();
// Update the stcking, only after we determine we can show the backdrop. The
// backdrop needs to be immediately behind the window that needs a backdrop.
container_->StackChildBelow(backdrop_window_, window_having_backdrop_);
// When overview is active, the backdrop should never be shown. However, it // When overview is active, the backdrop should never be shown. However, it
// must be laid out, since it should show up properly in the mini_views. // must be laid out, since it should show up properly in the mini_views.
if (!InOverviewSession()) if (backdrop_->IsVisible() || InOverviewSession())
backdrop_->Show(); return;
ScopedWindowVisibilityAnimationTypeResetter resetter{
backdrop_window_, WindowState::Get(window_having_backdrop_)->CanMaximize()
? WINDOW_VISIBILITY_ANIMATION_TYPE_STEP_END
: ::wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE};
backdrop_->Show();
} }
void BackdropController::Hide(bool destroy, bool animate) { void BackdropController::Hide(bool destroy, bool animate) {
...@@ -456,14 +578,13 @@ void BackdropController::Hide(bool destroy, bool animate) { ...@@ -456,14 +578,13 @@ void BackdropController::Hide(bool destroy, bool animate) {
bool BackdropController::BackdropShouldFullscreen() { bool BackdropController::BackdropShouldFullscreen() {
// TODO(afakhry): Define the correct behavior and revise this in a follow-up // TODO(afakhry): Define the correct behavior and revise this in a follow-up
// CL. // CL.
aura::Window* window = GetTopmostWindowWithBackdrop();
SplitViewController* split_view_controller = SplitViewController* split_view_controller =
SplitViewController::Get(root_window_); SplitViewController::Get(root_window_);
SplitViewController::State state = split_view_controller->state(); SplitViewController::State state = split_view_controller->state();
if ((state == SplitViewController::State::kLeftSnapped && if ((state == SplitViewController::State::kLeftSnapped &&
window == split_view_controller->left_window()) || window_having_backdrop_ == split_view_controller->left_window()) ||
(state == SplitViewController::State::kRightSnapped && (state == SplitViewController::State::kRightSnapped &&
window == split_view_controller->right_window())) { window_having_backdrop_ == split_view_controller->right_window())) {
return false; return false;
} }
...@@ -487,6 +608,8 @@ gfx::Rect BackdropController::GetBackdropBounds() { ...@@ -487,6 +608,8 @@ gfx::Rect BackdropController::GetBackdropBounds() {
} }
void BackdropController::Layout() { void BackdropController::Layout() {
DCHECK(backdrop_);
// Makes sure that the backdrop has the correct bounds if it should not be // Makes sure that the backdrop has the correct bounds if it should not be
// fullscreen size. // fullscreen size.
backdrop_->SetFullscreen(BackdropShouldFullscreen()); backdrop_->SetFullscreen(BackdropShouldFullscreen());
...@@ -494,22 +617,54 @@ void BackdropController::Layout() { ...@@ -494,22 +617,54 @@ void BackdropController::Layout() {
// TODO(oshima): The size of solid color layer can be smaller than texture's // TODO(oshima): The size of solid color layer can be smaller than texture's
// layer with fractional scale (crbug.com/9000220). Use adjusted bounds so // layer with fractional scale (crbug.com/9000220). Use adjusted bounds so
// that it can cover texture layer. Fix the bug and remove this. // that it can cover texture layer. Fix the bug and remove this.
auto* window = backdrop_window_; const gfx::Rect bounds =
gfx::Rect bounds = screen_util::GetDisplayBoundsInParent(window); screen_util::GetDisplayBoundsInParent(backdrop_window_);
backdrop_window_->SetBounds( backdrop_window_->SetBounds(
screen_util::SnapBoundsToDisplayEdge(bounds, window)); screen_util::SnapBoundsToDisplayEdge(bounds, backdrop_window_));
} else { } else {
backdrop_->SetBounds(GetBackdropBounds()); backdrop_->SetBounds(GetBackdropBounds());
} }
} }
void BackdropController::SetBackdropAnimationType(int type) { bool BackdropController::MaybeWaitForWindowAnimation() {
if (!backdrop_window_ || DCHECK(window_having_backdrop_);
::wm::GetWindowVisibilityAnimationType(backdrop_window_) == type) {
return; auto* animator = window_having_backdrop_->layer()->GetAnimator();
if (!animator->is_animating())
return false;
if (window_animation_waiter_ &&
window_animation_waiter_->animating_window() == window_having_backdrop_) {
return true;
} }
::wm::SetWindowVisibilityAnimationType(backdrop_window_, type); window_animation_waiter_.reset();
constexpr int kCheckedAnimations = ui::LayerAnimationElement::BOUNDS |
ui::LayerAnimationElement::TRANSFORM |
ui::LayerAnimationElement::OPACITY |
ui::LayerAnimationElement::VISIBILITY;
if (!animator->IsAnimatingOnePropertyOf(kCheckedAnimations))
return false;
window_animation_waiter_ =
std::make_unique<WindowAnimationWaiter>(this, window_having_backdrop_);
return true;
}
void BackdropController::MaybeUpdateLayout() {
if (backdrop_ && backdrop_->IsVisible())
Layout();
}
bool BackdropController::DoesWindowCauseBackdropUpdates(
aura::Window* window) const {
// Popups should not result in any backdrop updates. We also avoid unnecessary
// recursive calls to UpdateBackdrop() from the WorkspaceLayoutManager caused
// by the backdrop itself, even though we avoid recursion here via
// |pause_update_|.
return window->type() != aura::client::WINDOW_TYPE_POPUP &&
(!backdrop_ || window != backdrop_->GetNativeWindow());
} }
} // namespace ash } // namespace ash
...@@ -52,11 +52,12 @@ class ASH_EXPORT BackdropController : public AccessibilityObserver, ...@@ -52,11 +52,12 @@ class ASH_EXPORT BackdropController : public AccessibilityObserver,
explicit BackdropController(aura::Window* container); explicit BackdropController(aura::Window* container);
~BackdropController() override; ~BackdropController() override;
void OnWindowAddedToLayout(); void OnWindowAddedToLayout(aura::Window* window);
void OnWindowRemovedFromLayout(); void OnWindowRemovedFromLayout(aura::Window* window);
void OnChildWindowVisibilityChanged(); void OnChildWindowVisibilityChanged(aura::Window* window);
void OnWindowStackingChanged(); void OnBackdropWindowModePropertyChanged(aura::Window* window);
void OnPostWindowStateTypeChange(); void OnWindowStackingChanged(aura::Window* window);
void OnPostWindowStateTypeChange(aura::Window* window);
void OnDisplayMetricsChanged(); void OnDisplayMetricsChanged();
// Called when the desk content is changed in order to update the state of the // Called when the desk content is changed in order to update the state of the
...@@ -96,6 +97,7 @@ class ASH_EXPORT BackdropController : public AccessibilityObserver, ...@@ -96,6 +97,7 @@ class ASH_EXPORT BackdropController : public AccessibilityObserver,
void OnTabletModeEnded() override; void OnTabletModeEnded() override;
private: private:
class WindowAnimationWaiter;
friend class WorkspaceControllerTestApi; friend class WorkspaceControllerTestApi;
// Reenables updates previously pause by calling PauseUpdates(). // Reenables updates previously pause by calling PauseUpdates().
...@@ -103,7 +105,7 @@ class ASH_EXPORT BackdropController : public AccessibilityObserver, ...@@ -103,7 +105,7 @@ class ASH_EXPORT BackdropController : public AccessibilityObserver,
void UpdateBackdropInternal(); void UpdateBackdropInternal();
void EnsureBackdropWidget(BackdropWindowMode mode); void EnsureBackdropWidget();
void UpdateAccessibilityMode(); void UpdateAccessibilityMode();
...@@ -111,7 +113,9 @@ class ASH_EXPORT BackdropController : public AccessibilityObserver, ...@@ -111,7 +113,9 @@ class ASH_EXPORT BackdropController : public AccessibilityObserver,
bool WindowShouldHaveBackdrop(aura::Window* window); bool WindowShouldHaveBackdrop(aura::Window* window);
// Show the backdrop window. // Show the backdrop window if the |window_having_backdrop_| is not animating,
// otherwise it will wait for that animation to finish. If it can show the
// backdrop, it will update its bounds and stacking order before its shown.
void Show(); void Show();
// Hide the backdrop window. If |destroy| is true, the backdrop widget will be // Hide the backdrop window. If |destroy| is true, the backdrop widget will be
...@@ -130,8 +134,17 @@ class ASH_EXPORT BackdropController : public AccessibilityObserver, ...@@ -130,8 +134,17 @@ class ASH_EXPORT BackdropController : public AccessibilityObserver,
// backdrop bounds should be the bounds of the snapped window. // backdrop bounds should be the bounds of the snapped window.
gfx::Rect GetBackdropBounds(); gfx::Rect GetBackdropBounds();
// Sets the animtion type of |backdrop_window_| to |type|. // If |window_having_backdrop_| is animating such that we shouldn't update the
void SetBackdropAnimationType(int type); // backdrop until that animation is complete, starts observing this animation
// (if not already done) and returns true. Returns false otherwise.
bool MaybeWaitForWindowAnimation();
// Updates the layout of the backdrop if one exists and is visible.
void MaybeUpdateLayout();
// Returns true if changes to |window| may require updating the backdrop
// visibility and availability.
bool DoesWindowCauseBackdropUpdates(aura::Window* window) const;
aura::Window* root_window_; aura::Window* root_window_;
...@@ -141,9 +154,16 @@ class ASH_EXPORT BackdropController : public AccessibilityObserver, ...@@ -141,9 +154,16 @@ class ASH_EXPORT BackdropController : public AccessibilityObserver,
// aura::Window for |backdrop_|. // aura::Window for |backdrop_|.
aura::Window* backdrop_window_ = nullptr; aura::Window* backdrop_window_ = nullptr;
// The window for which a backdrop has been installed.
aura::Window* window_having_backdrop_ = nullptr;
// The container of the window that should have a backdrop. // The container of the window that should have a backdrop.
aura::Window* container_; aura::Window* container_;
// If |window_having_backdrop_| is animating while we're trying to show the
// backdrop, we postpone showing it until the animation completes.
std::unique_ptr<WindowAnimationWaiter> window_animation_waiter_;
// Event hanlder used to implement actions for accessibility. // Event hanlder used to implement actions for accessibility.
std::unique_ptr<ui::EventHandler> backdrop_event_handler_; std::unique_ptr<ui::EventHandler> backdrop_event_handler_;
ui::EventHandler* original_event_handler_ = nullptr; ui::EventHandler* original_event_handler_ = nullptr;
......
...@@ -148,7 +148,7 @@ void WorkspaceLayoutManager::OnWindowAddedToLayout(aura::Window* child) { ...@@ -148,7 +148,7 @@ void WorkspaceLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
UpdateShelfVisibility(); UpdateShelfVisibility();
UpdateFullscreenState(); UpdateFullscreenState();
backdrop_controller_->OnWindowAddedToLayout(); backdrop_controller_->OnWindowAddedToLayout(child);
WindowPositioner::RearrangeVisibleWindowOnShow(child); WindowPositioner::RearrangeVisibleWindowOnShow(child);
if (Shell::Get()->screen_pinning_controller()->IsPinned()) if (Shell::Get()->screen_pinning_controller()->IsPinned())
WindowState::Get(child)->DisableZOrdering(nullptr); WindowState::Get(child)->DisableZOrdering(nullptr);
...@@ -178,7 +178,7 @@ void WorkspaceLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) { ...@@ -178,7 +178,7 @@ void WorkspaceLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
void WorkspaceLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) { void WorkspaceLayoutManager::OnWindowRemovedFromLayout(aura::Window* child) {
UpdateShelfVisibility(); UpdateShelfVisibility();
UpdateFullscreenState(); UpdateFullscreenState();
backdrop_controller_->OnWindowRemovedFromLayout(); backdrop_controller_->OnWindowRemovedFromLayout(child);
} }
void WorkspaceLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child, void WorkspaceLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
...@@ -194,7 +194,7 @@ void WorkspaceLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child, ...@@ -194,7 +194,7 @@ void WorkspaceLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
WindowPositioner::RearrangeVisibleWindowOnHideOrRemove(child); WindowPositioner::RearrangeVisibleWindowOnHideOrRemove(child);
UpdateFullscreenState(); UpdateFullscreenState();
UpdateShelfVisibility(); UpdateShelfVisibility();
backdrop_controller_->OnChildWindowVisibilityChanged(); backdrop_controller_->OnChildWindowVisibilityChanged(child);
} }
void WorkspaceLayoutManager::SetChildBounds(aura::Window* child, void WorkspaceLayoutManager::SetChildBounds(aura::Window* child,
...@@ -320,14 +320,14 @@ void WorkspaceLayoutManager::OnWindowPropertyChanged(aura::Window* window, ...@@ -320,14 +320,14 @@ void WorkspaceLayoutManager::OnWindowPropertyChanged(aura::Window* window,
container->AddChild(window); container->AddChild(window);
} }
} else if (key == kBackdropWindowMode) { } else if (key == kBackdropWindowMode) {
backdrop_controller_->UpdateBackdrop(); backdrop_controller_->OnBackdropWindowModePropertyChanged(window);
} }
} }
void WorkspaceLayoutManager::OnWindowStackingChanged(aura::Window* window) { void WorkspaceLayoutManager::OnWindowStackingChanged(aura::Window* window) {
UpdateShelfVisibility(); UpdateShelfVisibility();
UpdateFullscreenState(); UpdateFullscreenState();
backdrop_controller_->OnWindowStackingChanged(); backdrop_controller_->OnWindowStackingChanged(window);
} }
void WorkspaceLayoutManager::OnWindowDestroying(aura::Window* window) { void WorkspaceLayoutManager::OnWindowDestroying(aura::Window* window) {
...@@ -386,7 +386,7 @@ void WorkspaceLayoutManager::OnPostWindowStateTypeChange( ...@@ -386,7 +386,7 @@ void WorkspaceLayoutManager::OnPostWindowStateTypeChange(
} }
UpdateShelfVisibility(); UpdateShelfVisibility();
backdrop_controller_->OnPostWindowStateTypeChange(); backdrop_controller_->OnPostWindowStateTypeChange(window_state->window());
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment