[Merge to M-76] Virtual Desks: Fix multi-profile behavior
- Windows from an inactive user should not show in the desk's
mini_view.
- Regardless of the their desks, windows of the inactive user
should remain hidden.
TBR=jamescook@chromium.org
BUG=972765
TEST=Manual, added new test.
(cherry picked from commit 36e697d0e450ad340c119570edade7449011c109)
Change-Id: I0dc3b7b65fce390430b5a4b8c1ae11b74b831311
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1653839
Commit-Queue: Ahmed Fakhry <afakhry@chromium.org>
Reviewed-by: James Cook <jamescook@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#668181}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1659855
Reviewed-by: Ahmed Fakhry <afakhry@chromium.org>
Cr-Commit-Position: refs/branch-heads/3809@{#309}
Cr-Branched-From: d82dec1a818f378c464ba307ddd9c92133eac355-refs/heads/master@{#665002}
diff --git a/ash/multi_user/multi_user_window_manager_impl.cc b/ash/multi_user/multi_user_window_manager_impl.cc
index 22188ba..63167d1 100644
--- a/ash/multi_user/multi_user_window_manager_impl.cc
+++ b/ash/multi_user/multi_user_window_manager_impl.cc
@@ -15,6 +15,7 @@
#include "ash/public/cpp/wallpaper_user_info.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
+#include "ash/wm/desks/desks_util.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "base/auto_reset.h"
#include "base/macros.h"
@@ -448,7 +449,7 @@
aura::Window* window,
bool visible,
base::TimeDelta animation_time) {
- if (window->IsVisible() == visible)
+ if (desks_util::BelongsToActiveDesk(window) && window->IsVisible() == visible)
return;
// Hiding a system modal dialog should not be allowed. Instead we switch to
diff --git a/ash/wm/desks/desk_preview_view.cc b/ash/wm/desks/desk_preview_view.cc
index f4c44e59..46c2a6d 100644
--- a/ash/wm/desks/desk_preview_view.cc
+++ b/ash/wm/desks/desk_preview_view.cc
@@ -4,6 +4,7 @@
#include "ash/wm/desks/desk_preview_view.h"
+#include "ash/multi_user/multi_user_window_manager_impl.h"
#include "ash/public/cpp/window_properties.h"
#include "ash/wallpaper/wallpaper_base_view.h"
#include "ash/wm/desks/desk_mini_view.h"
@@ -43,6 +44,24 @@
bool should_reset_transform = false;
};
+// Returns true if |window| can be shown in the desk's preview according to its
+// multi-profile ownership status (i.e. can only be shown if it belongs to the
+// active user).
+bool CanShowWindowForMultiProfile(aura::Window* window) {
+ MultiUserWindowManager* multi_user_window_manager =
+ MultiUserWindowManagerImpl::Get();
+ if (!multi_user_window_manager)
+ return true;
+
+ const AccountId account_id =
+ multi_user_window_manager->GetUserPresentingWindow(window);
+ // An empty account ID is returned if the window is presented for all users.
+ if (!account_id.is_valid())
+ return true;
+
+ return account_id == multi_user_window_manager->CurrentAccountId();
+}
+
// Recursively mirrors |source_layer| and its children and adds them as children
// of |parent|, taking into account the given |layers_data|.
void MirrorLayerTree(ui::Layer* source_layer,
@@ -93,6 +112,11 @@
return;
}
+ if (!CanShowWindowForMultiProfile(window)) {
+ layer_data.should_skip_layer = true;
+ return;
+ }
+
// Windows transformed into position in the overview mode grid should be
// mirrored and the transforms of the mirrored layers should be reset to
// identity.
diff --git a/ash/wm/desks/desks_unittests.cc b/ash/wm/desks/desks_unittests.cc
index 8694d4b..6f5dc4f5 100644
--- a/ash/wm/desks/desks_unittests.cc
+++ b/ash/wm/desks/desks_unittests.cc
@@ -4,7 +4,10 @@
#include <vector>
+#include "ash/multi_user/multi_user_window_manager_impl.h"
#include "ash/public/cpp/ash_features.h"
+#include "ash/public/cpp/multi_user_window_manager.h"
+#include "ash/public/cpp/multi_user_window_manager_delegate.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/window_factory.h"
@@ -1250,6 +1253,120 @@
->current_indicator_state());
}
+namespace {
+
+constexpr char kUser1Email[] = "user1@desks";
+constexpr char kUser2Email[] = "user2@desks";
+
+} // namespace
+
+class DesksMultiUserTest : public NoSessionAshTestBase,
+ public MultiUserWindowManagerDelegate {
+ public:
+ DesksMultiUserTest() = default;
+ ~DesksMultiUserTest() override = default;
+
+ MultiUserWindowManager* multi_user_window_manager() {
+ return multi_user_window_manager_.get();
+ }
+
+ // AshTestBase:
+ void SetUp() override {
+ scoped_feature_list_.InitAndEnableFeature(features::kVirtualDesks);
+
+ NoSessionAshTestBase::SetUp();
+ TestSessionControllerClient* session_controller =
+ GetSessionControllerClient();
+ session_controller->Reset();
+ session_controller->AddUserSession(kUser1Email);
+ session_controller->AddUserSession(kUser2Email);
+
+ // Simulate user 1 login.
+ SwitchActiveUser(GetUser1AccountId());
+ multi_user_window_manager_ =
+ MultiUserWindowManager::Create(this, GetUser1AccountId());
+ MultiUserWindowManagerImpl::Get()->SetAnimationSpeedForTest(
+ MultiUserWindowManagerImpl::ANIMATION_SPEED_DISABLED);
+ }
+
+ void TearDown() override {
+ multi_user_window_manager_.reset();
+ NoSessionAshTestBase::TearDown();
+ }
+
+ // MultiUserWindowManagerDelegate:
+ void OnWindowOwnerEntryChanged(aura::Window* window,
+ const AccountId& account_id,
+ bool was_minimized,
+ bool teleported) override {}
+ void OnTransitionUserShelfToNewAccount() override {}
+
+ AccountId GetUser1AccountId() const {
+ return AccountId::FromUserEmail(kUser1Email);
+ }
+
+ AccountId GetUser2AccountId() const {
+ return AccountId::FromUserEmail(kUser2Email);
+ }
+
+ void SwitchActiveUser(const AccountId& account_id) {
+ GetSessionControllerClient()->SwitchActiveUser(account_id);
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+ std::unique_ptr<MultiUserWindowManager> multi_user_window_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(DesksMultiUserTest);
+};
+
+TEST_F(DesksMultiUserTest, SwitchUsersBackAndForth) {
+ // Create two desks with two windows on each, one window that belongs to the
+ // first user, and the other belongs to the second.
+ auto* controller = DesksController::Get();
+ controller->NewDesk();
+ ASSERT_EQ(2u, controller->desks().size());
+ Desk* desk_1 = controller->desks()[0].get();
+ Desk* desk_2 = controller->desks()[1].get();
+ auto win0 = CreateTestWindow(gfx::Rect(0, 0, 250, 100));
+ multi_user_window_manager()->SetWindowOwner(win0.get(), GetUser1AccountId());
+ EXPECT_TRUE(win0->IsVisible());
+ ActivateDesk(desk_2);
+ auto win1 = CreateTestWindow(gfx::Rect(50, 50, 200, 200));
+ multi_user_window_manager()->SetWindowOwner(win1.get(), GetUser1AccountId());
+ EXPECT_FALSE(win0->IsVisible());
+ EXPECT_TRUE(win1->IsVisible());
+
+ // Switch to user_2 and expect no windows from user_1 is visible regardless of
+ // the desk.
+ SwitchActiveUser(GetUser2AccountId());
+ EXPECT_FALSE(win0->IsVisible());
+ EXPECT_FALSE(win1->IsVisible());
+
+ auto win2 = CreateTestWindow(gfx::Rect(0, 0, 250, 200));
+ multi_user_window_manager()->SetWindowOwner(win2.get(), GetUser2AccountId());
+ EXPECT_TRUE(win2->IsVisible());
+ ActivateDesk(desk_1);
+ auto win3 = CreateTestWindow(gfx::Rect(0, 0, 250, 200));
+ multi_user_window_manager()->SetWindowOwner(win3.get(), GetUser2AccountId());
+ EXPECT_FALSE(win0->IsVisible());
+ EXPECT_FALSE(win1->IsVisible());
+ EXPECT_FALSE(win2->IsVisible());
+ EXPECT_TRUE(win3->IsVisible());
+
+ // Similarly when switching back to user_1.
+ SwitchActiveUser(GetUser1AccountId());
+ EXPECT_TRUE(win0->IsVisible());
+ EXPECT_FALSE(win1->IsVisible());
+ EXPECT_FALSE(win2->IsVisible());
+ EXPECT_FALSE(win3->IsVisible());
+ ActivateDesk(desk_2);
+ EXPECT_FALSE(win0->IsVisible());
+ EXPECT_TRUE(win1->IsVisible());
+ EXPECT_FALSE(win2->IsVisible());
+ EXPECT_FALSE(win3->IsVisible());
+}
+
// TODO(afakhry): Add more tests:
// - Always on top windows are not tracked by any desk.
// - Reusing containers when desks are removed and created.