diff options
author | afakhry <afakhry@chromium.org> | 2015-01-12 09:57:43 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-01-12 17:58:37 +0000 |
commit | cae0618f6fff0122063d231ff3217788707eaaaf (patch) | |
tree | 4cd4b1e8d4ea309bda96a78bb1f8c9a7b1d8f11c | |
parent | 7a5b2859441e471e1ac8c459d997918af8e8cd0f (diff) | |
download | chromium_src-cae0618f6fff0122063d231ff3217788707eaaaf.zip chromium_src-cae0618f6fff0122063d231ff3217788707eaaaf.tar.gz chromium_src-cae0618f6fff0122063d231ff3217788707eaaaf.tar.bz2 |
System modal dialog unhide shelf launcher, and prevents going into maximized mode.
When shelf is auto hidden, displaying a system modal dialog used to
unhide it. That was because the ShelfLayoutManager when updating the
shelf visibility, it used to ask the MruWindowTracker to build a list of
the windows. This list used to exclude the unfocusable windows (due to
the system modal dialog), So the returned list used to be empty which
means the shelf should be unhidden.
We actually need the list of all visible windows regardless of their
focusability.
Two unit tests has been written to validate the correct behavior in both
single and dual display modes.
BUG=277893, 447720
TEST=ash_unittests --gtest_filter=ShelfLayoutManagerTest.ShelfWithSystemModalWindowSingleDisplay, ShelfLayoutManagerTest.ShelfWithSystemModalWindowDualDisplay, MaximizeModeWindowManagerTest.GoingToMaximizedWithModalDialogPresent
Review URL: https://codereview.chromium.org/780113002
Cr-Commit-Position: refs/heads/master@{#311063}
-rw-r--r-- | ash/accelerators/accelerator_controller.cc | 2 | ||||
-rw-r--r-- | ash/focus_cycler.cc | 3 | ||||
-rw-r--r-- | ash/shelf/shelf_layout_manager.cc | 2 | ||||
-rw-r--r-- | ash/shelf/shelf_layout_manager_unittest.cc | 81 | ||||
-rw-r--r-- | ash/shell.cc | 7 | ||||
-rw-r--r-- | ash/wm/ash_focus_rules.cc | 12 | ||||
-rw-r--r-- | ash/wm/ash_focus_rules.h | 4 | ||||
-rw-r--r-- | ash/wm/maximize_mode/maximize_mode_window_manager.cc | 3 | ||||
-rw-r--r-- | ash/wm/maximize_mode/maximize_mode_window_manager_unittest.cc | 76 | ||||
-rw-r--r-- | ash/wm/mru_window_tracker.cc | 47 | ||||
-rw-r--r-- | ash/wm/mru_window_tracker.h | 35 | ||||
-rw-r--r-- | ash/wm/window_positioner.cc | 8 | ||||
-rw-r--r-- | chrome/browser/chromeos/extensions/wallpaper_private_api.cc | 3 |
13 files changed, 243 insertions, 40 deletions
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc index 61e00f6..c951f2e 100644 --- a/ash/accelerators/accelerator_controller.cc +++ b/ash/accelerators/accelerator_controller.cc @@ -1319,7 +1319,7 @@ AcceleratorController::GetAcceleratorProcessingRestriction(int action) { // cycling through its window elements. return RESTRICTION_PREVENT_PROCESSING_AND_PROPAGATION; } - if (MruWindowTracker::BuildWindowList().empty() && + if (shell->mru_window_tracker()->BuildMruWindowList().empty() && actions_needing_window_.find(action) != actions_needing_window_.end()) { Shell::GetInstance()->accessibility_delegate()->TriggerAccessibilityAlert( ui::A11Y_ALERT_WINDOW_NEEDED); diff --git a/ash/focus_cycler.cc b/ash/focus_cycler.cc index 2ccf256..402fdc8 100644 --- a/ash/focus_cycler.cc +++ b/ash/focus_cycler.cc @@ -19,7 +19,8 @@ namespace ash { namespace { bool HasFocusableWindow() { - return !MruWindowTracker::BuildWindowList().empty(); + return !ash::Shell::GetInstance()-> + mru_window_tracker()->BuildMruWindowList().empty(); } } // namespace diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc index 08831e2..b096b8f 100644 --- a/ash/shelf/shelf_layout_manager.cc +++ b/ash/shelf/shelf_layout_manager.cc @@ -1031,7 +1031,7 @@ ShelfAutoHideState ShelfLayoutManager::CalculateAutoHideState( return SHELF_AUTO_HIDE_SHOWN; const std::vector<aura::Window*> windows = - ash::MruWindowTracker::BuildWindowList(); + shell->mru_window_tracker()->BuildWindowListIgnoreModal(); // Process the window list and check if there are any visible windows. bool visible_window = false; diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc index eefeda7..1ad54a8 100644 --- a/ash/shelf/shelf_layout_manager_unittest.cc +++ b/ash/shelf/shelf_layout_manager_unittest.cc @@ -1472,6 +1472,87 @@ TEST_F(ShelfLayoutManagerTest, OpenAppListWithShelfHiddenState) { EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state()); } +// Tests the correct behavior of the shelf when there is a system modal window +// open when we have a single display. +TEST_F(ShelfLayoutManagerTest, ShelfWithSystemModalWindowSingleDisplay) { + Shell* shell = Shell::GetInstance(); + ShelfLayoutManager* shelf = GetShelfLayoutManager(); + shelf->LayoutShelf(); + shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); + + aura::Window* window = CreateTestWindow(); + window->SetBounds(gfx::Rect(0, 0, 100, 100)); + window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); + window->Show(); + wm::ActivateWindow(window); + + // Enable system modal dialog, and make sure shelf is still hidden. + shell->SimulateModalWindowOpenForTesting(true); + EXPECT_TRUE(shell->IsSystemModalWindowOpen()); + EXPECT_FALSE(wm::CanActivateWindow(window)); + shell->UpdateShelfVisibility(); + EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state()); + EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state()); +} + +// Tests the correct behavior of the shelf when there is a system modal window +// open when we have dual display. +TEST_F(ShelfLayoutManagerTest, ShelfWithSystemModalWindowDualDisplay) { + if (!SupportsMultipleDisplays()) + return; + + // Create two displays. + Shell* shell = Shell::GetInstance(); + DisplayManager* display_manager = shell->display_manager(); + UpdateDisplay("200x200,100x100"); + EXPECT_EQ(2U, display_manager->GetNumDisplays()); + + DisplayController* display_controller = shell->display_controller(); + aura::Window::Windows root_windows = display_controller->GetAllRootWindows(); + EXPECT_EQ(root_windows.size(), 2U); + + // Get the shelves in both displays and set them to be 'AutoHide'. + ShelfLayoutManager* shelf_1 = + GetRootWindowController(root_windows[0])->GetShelfLayoutManager(); + ShelfLayoutManager* shelf_2 = + GetRootWindowController(root_windows[1])->GetShelfLayoutManager(); + EXPECT_NE(shelf_1, shelf_2); + EXPECT_NE(shelf_1->shelf_widget()->GetNativeWindow()->GetRootWindow(), + shelf_2->shelf_widget()->GetNativeWindow()->GetRootWindow()); + shelf_1->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); + shelf_1->LayoutShelf(); + shelf_2->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); + shelf_2->LayoutShelf(); + + // Create a window in each display and show them in maximized state. + aura::Window* window_1 = CreateTestWindowInParent(root_windows[0]); + window_1->SetBounds(gfx::Rect(0, 0, 100, 100)); + window_1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); + window_1->Show(); + aura::Window* window_2 = CreateTestWindowInParent(root_windows[1]); + window_2->SetBounds(gfx::Rect(201, 0, 100, 100)); + window_2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); + window_2->Show(); + + EXPECT_EQ(shelf_1->shelf_widget()->GetNativeWindow()->GetRootWindow(), + window_1->GetRootWindow()); + EXPECT_EQ(shelf_2->shelf_widget()->GetNativeWindow()->GetRootWindow(), + window_2->GetRootWindow()); + EXPECT_TRUE(window_1->IsVisible()); + EXPECT_TRUE(window_2->IsVisible()); + + // Enable system modal dialog, and make sure both shelves are still hidden. + shell->SimulateModalWindowOpenForTesting(true); + EXPECT_TRUE(shell->IsSystemModalWindowOpen()); + EXPECT_FALSE(wm::CanActivateWindow(window_1)); + EXPECT_FALSE(wm::CanActivateWindow(window_2)); + shell->UpdateShelfVisibility(); + EXPECT_EQ(SHELF_AUTO_HIDE, shelf_1->visibility_state()); + EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf_1->auto_hide_state()); + EXPECT_EQ(SHELF_AUTO_HIDE, shelf_2->visibility_state()); + EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf_2->auto_hide_state()); +} + // Tests that the shelf is only hidden for a fullscreen window at the front and // toggles visibility when another window is activated. TEST_F(ShelfLayoutManagerTest, FullscreenWindowInFrontHidesShelf) { diff --git a/ash/shell.cc b/ash/shell.cc index 96fc38c..aabbcce 100644 --- a/ash/shell.cc +++ b/ash/shell.cc @@ -878,8 +878,10 @@ void Shell::Init(const ShellInitParams& init_params) { env_filter_.reset(new ::wm::CompoundEventFilter); AddPreTargetHandler(env_filter_.get()); + wm::AshFocusRules* focus_rules = new wm::AshFocusRules(); + ::wm::FocusController* focus_controller = - new ::wm::FocusController(new wm::AshFocusRules); + new ::wm::FocusController(focus_rules); focus_client_.reset(focus_controller); activation_client_ = focus_controller; activation_client_->AddObserver(this); @@ -974,7 +976,8 @@ void Shell::Init(const ShellInitParams& init_params) { magnification_controller_.reset( MagnificationController::CreateInstance()); - mru_window_tracker_.reset(new MruWindowTracker(activation_client_)); + mru_window_tracker_.reset(new MruWindowTracker(activation_client_, + focus_rules)); partial_magnification_controller_.reset( new PartialMagnificationController()); diff --git a/ash/wm/ash_focus_rules.cc b/ash/wm/ash_focus_rules.cc index c38c7d3..6bcae35 100644 --- a/ash/wm/ash_focus_rules.cc +++ b/ash/wm/ash_focus_rules.cc @@ -53,6 +53,18 @@ AshFocusRules::AshFocusRules() { AshFocusRules::~AshFocusRules() { } +bool AshFocusRules::IsWindowConsideredActivatable(aura::Window* window) const { + // Only toplevel windows can be activated. + if (!IsToplevelWindow(window)) + return false; + + // The window must be visible. + if (!IsWindowConsideredVisibleForActivation(window)) + return false; + + return true; +} + //////////////////////////////////////////////////////////////////////////////// // AshFocusRules, ::wm::FocusRules: diff --git a/ash/wm/ash_focus_rules.h b/ash/wm/ash_focus_rules.h index f32ce87..70cf56997 100644 --- a/ash/wm/ash_focus_rules.h +++ b/ash/wm/ash_focus_rules.h @@ -18,6 +18,10 @@ class ASH_EXPORT AshFocusRules : public ::wm::BaseFocusRules { AshFocusRules(); ~AshFocusRules() override; + // Tests if the given |window| can be activated, ignoring the system modal + // dialog state. + bool IsWindowConsideredActivatable(aura::Window* window) const; + private: // Overridden from ::wm::BaseFocusRules: bool SupportsChildActivation(aura::Window* window) const override; diff --git a/ash/wm/maximize_mode/maximize_mode_window_manager.cc b/ash/wm/maximize_mode/maximize_mode_window_manager.cc index 7506bee..231fdae 100644 --- a/ash/wm/maximize_mode/maximize_mode_window_manager.cc +++ b/ash/wm/maximize_mode/maximize_mode_window_manager.cc @@ -182,7 +182,8 @@ MaximizeModeWindowManager::MaximizeModeWindowManager() } void MaximizeModeWindowManager::MaximizeAllWindows() { - MruWindowTracker::WindowList windows = MruWindowTracker::BuildWindowList(); + MruWindowTracker::WindowList windows = ash::Shell::GetInstance()-> + mru_window_tracker()->BuildWindowListIgnoreModal(); // Add all existing Mru windows. for (MruWindowTracker::WindowList::iterator window = windows.begin(); window != windows.end(); ++window) { diff --git a/ash/wm/maximize_mode/maximize_mode_window_manager_unittest.cc b/ash/wm/maximize_mode/maximize_mode_window_manager_unittest.cc index d2e06a1..a57fa75 100644 --- a/ash/wm/maximize_mode/maximize_mode_window_manager_unittest.cc +++ b/ash/wm/maximize_mode/maximize_mode_window_manager_unittest.cc @@ -213,6 +213,73 @@ TEST_F(MaximizeModeWindowManagerTest, PreCreateWindows) { EXPECT_EQ(rect.ToString(), w8->bounds().ToString()); } +// The same test as the above but while a system modal dialog is shown. +TEST_F(MaximizeModeWindowManagerTest, GoingToMaximizedWithModalDialogPresent) { + // Bounds for windows we know can be controlled. + gfx::Rect rect1(10, 10, 200, 50); + gfx::Rect rect2(10, 60, 200, 50); + gfx::Rect rect3(20, 140, 100, 100); + // Bounds for anything else. + gfx::Rect rect(80, 90, 100, 110); + scoped_ptr<aura::Window> w1(CreateWindow(ui::wm::WINDOW_TYPE_NORMAL, rect1)); + scoped_ptr<aura::Window> w2(CreateWindow(ui::wm::WINDOW_TYPE_NORMAL, rect2)); + scoped_ptr<aura::Window> w3( + CreateFixedSizeNonMaximizableWindow(ui::wm::WINDOW_TYPE_NORMAL, rect3)); + scoped_ptr<aura::Window> w4(CreateWindow(ui::wm::WINDOW_TYPE_PANEL, rect)); + scoped_ptr<aura::Window> w5(CreateWindow(ui::wm::WINDOW_TYPE_POPUP, rect)); + scoped_ptr<aura::Window> w6(CreateWindow(ui::wm::WINDOW_TYPE_CONTROL, rect)); + scoped_ptr<aura::Window> w7(CreateWindow(ui::wm::WINDOW_TYPE_MENU, rect)); + scoped_ptr<aura::Window> w8(CreateWindow(ui::wm::WINDOW_TYPE_TOOLTIP, rect)); + EXPECT_FALSE(wm::GetWindowState(w1.get())->IsMaximized()); + EXPECT_FALSE(wm::GetWindowState(w2.get())->IsMaximized()); + EXPECT_FALSE(wm::GetWindowState(w3.get())->IsMaximized()); + EXPECT_EQ(rect1.ToString(), w1->bounds().ToString()); + EXPECT_EQ(rect2.ToString(), w2->bounds().ToString()); + EXPECT_EQ(rect3.ToString(), w3->bounds().ToString()); + + // Enable system modal dialog, and make sure both shelves are still hidden. + ash::Shell::GetInstance()->SimulateModalWindowOpenForTesting(true); + EXPECT_TRUE(ash::Shell::GetInstance()->IsSystemModalWindowOpen()); + + // Create the manager and make sure that all qualifying windows were detected + // and changed. + ash::MaximizeModeWindowManager* manager = CreateMaximizeModeWindowManager(); + ASSERT_TRUE(manager); + EXPECT_EQ(3, manager->GetNumberOfManagedWindows()); + EXPECT_TRUE(wm::GetWindowState(w1.get())->IsMaximized()); + EXPECT_TRUE(wm::GetWindowState(w2.get())->IsMaximized()); + EXPECT_FALSE(wm::GetWindowState(w3.get())->IsMaximized()); + EXPECT_NE(rect3.origin().ToString(), w3->bounds().origin().ToString()); + EXPECT_EQ(rect3.size().ToString(), w3->bounds().size().ToString()); + + // All other windows should not have been touched. + EXPECT_FALSE(wm::GetWindowState(w4.get())->IsMaximized()); + EXPECT_FALSE(wm::GetWindowState(w5.get())->IsMaximized()); + EXPECT_FALSE(wm::GetWindowState(w6.get())->IsMaximized()); + EXPECT_FALSE(wm::GetWindowState(w7.get())->IsMaximized()); + EXPECT_FALSE(wm::GetWindowState(w8.get())->IsMaximized()); + EXPECT_EQ(rect.ToString(), w4->bounds().ToString()); + EXPECT_EQ(rect.ToString(), w5->bounds().ToString()); + EXPECT_EQ(rect.ToString(), w6->bounds().ToString()); + EXPECT_EQ(rect.ToString(), w7->bounds().ToString()); + EXPECT_EQ(rect.ToString(), w8->bounds().ToString()); + + // Destroy the manager again and check that the windows return to their + // previous state. + DestroyMaximizeModeWindowManager(); + EXPECT_FALSE(wm::GetWindowState(w1.get())->IsMaximized()); + EXPECT_FALSE(wm::GetWindowState(w2.get())->IsMaximized()); + EXPECT_FALSE(wm::GetWindowState(w3.get())->IsMaximized()); + EXPECT_EQ(rect1.ToString(), w1->bounds().ToString()); + EXPECT_EQ(rect2.ToString(), w2->bounds().ToString()); + EXPECT_EQ(rect3.ToString(), w3->bounds().ToString()); + EXPECT_EQ(rect.ToString(), w4->bounds().ToString()); + EXPECT_EQ(rect.ToString(), w5->bounds().ToString()); + EXPECT_EQ(rect.ToString(), w6->bounds().ToString()); + EXPECT_EQ(rect.ToString(), w7->bounds().ToString()); + EXPECT_EQ(rect.ToString(), w8->bounds().ToString()); +} + // Test that non-maximizable windows get properly handled when going into // maximized mode. TEST_F(MaximizeModeWindowManagerTest, @@ -679,7 +746,8 @@ TEST_F(MaximizeModeWindowManagerTest, ModeChangeKeepsMRUOrder) { // The windows should be in the reverse order of creation in the MRU list. { - MruWindowTracker::WindowList windows = MruWindowTracker::BuildWindowList(); + MruWindowTracker::WindowList windows = ash::Shell::GetInstance()-> + mru_window_tracker()->BuildMruWindowList(); EXPECT_EQ(w1.get(), windows[4]); EXPECT_EQ(w2.get(), windows[3]); EXPECT_EQ(w3.get(), windows[2]); @@ -692,7 +760,8 @@ TEST_F(MaximizeModeWindowManagerTest, ModeChangeKeepsMRUOrder) { ASSERT_TRUE(manager); EXPECT_EQ(5, manager->GetNumberOfManagedWindows()); { - MruWindowTracker::WindowList windows = MruWindowTracker::BuildWindowList(); + MruWindowTracker::WindowList windows = ash::Shell::GetInstance()-> + mru_window_tracker()->BuildMruWindowList(); // We do not test maximization here again since that was done already. EXPECT_EQ(w1.get(), windows[4]); EXPECT_EQ(w2.get(), windows[3]); @@ -704,7 +773,8 @@ TEST_F(MaximizeModeWindowManagerTest, ModeChangeKeepsMRUOrder) { // Destroying should still keep the order. DestroyMaximizeModeWindowManager(); { - MruWindowTracker::WindowList windows = MruWindowTracker::BuildWindowList(); + MruWindowTracker::WindowList windows = ash::Shell::GetInstance()-> + mru_window_tracker()->BuildMruWindowList(); // We do not test maximization here again since that was done already. EXPECT_EQ(w1.get(), windows[4]); EXPECT_EQ(w2.get(), windows[3]); diff --git a/ash/wm/mru_window_tracker.cc b/ash/wm/mru_window_tracker.cc index 0952f49..f006d45 100644 --- a/ash/wm/mru_window_tracker.cc +++ b/ash/wm/mru_window_tracker.cc @@ -10,9 +10,11 @@ #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/switchable_windows.h" +#include "ash/wm/ash_focus_rules.h" #include "ash/wm/window_state.h" #include "ash/wm/window_util.h" #include "ash/wm/workspace_controller.h" +#include "base/bind.h" #include "ui/aura/window_event_dispatcher.h" #include "ui/events/event.h" #include "ui/events/event_handler.h" @@ -22,6 +24,8 @@ namespace ash { namespace { +typedef base::Callback<bool(aura::Window*)> CanActivateWindowPredicate; + // Adds the windows that can be cycled through for the specified window id to // |windows|. void AddTrackedWindows(aura::Window* root, @@ -54,8 +58,11 @@ bool CompareWindowState(aura::Window* w1, aura::Window* w2) { // Returns a list of windows ordered by their stacking order. // If |mru_windows| is passed, these windows are moved to the front of the list. +// It uses the given |should_include_window_predicate| to determine whether to +// include a window in the returned list or not. MruWindowTracker::WindowList BuildWindowListInternal( - const std::list<aura::Window*>* mru_windows) { + const std::list<aura::Window*>* mru_windows, + const CanActivateWindowPredicate& should_include_window_predicate) { MruWindowTracker::WindowList windows; aura::Window::Windows root_windows = Shell::GetAllRootWindows(); @@ -78,12 +85,13 @@ MruWindowTracker::WindowList BuildWindowListInternal( AddDraggedWindows(active_root, &windows); // Removes unfocusable windows. - MruWindowTracker::WindowList::iterator last = - std::remove_if( - windows.begin(), - windows.end(), - std::not1(std::ptr_fun(ash::wm::CanActivateWindow))); - windows.erase(last, windows.end()); + std::vector<aura::Window*>::iterator itr = windows.begin(); + while (itr != windows.end()) { + if (!should_include_window_predicate.Run(*itr)) + itr = windows.erase(itr); + else + ++itr; + } // Put the windows in the mru_windows list at the head, if it's available. if (mru_windows) { @@ -95,7 +103,7 @@ MruWindowTracker::WindowList BuildWindowListInternal( // Exclude windows in non-switchable containers and those which cannot // be activated. if (!IsSwitchableContainer((*ix)->parent()) || - !ash::wm::CanActivateWindow(*ix)) { + !should_include_window_predicate.Run(*ix)) { continue; } @@ -123,8 +131,10 @@ MruWindowTracker::WindowList BuildWindowListInternal( // MruWindowTracker, public: MruWindowTracker::MruWindowTracker( - aura::client::ActivationClient* activation_client) + aura::client::ActivationClient* activation_client, + ash::wm::AshFocusRules* focus_rules) : activation_client_(activation_client), + focus_rules_(focus_rules), ignore_window_activations_(false) { activation_client_->AddObserver(this); } @@ -138,13 +148,17 @@ MruWindowTracker::~MruWindowTracker() { activation_client_->RemoveObserver(this); } -// static -MruWindowTracker::WindowList MruWindowTracker::BuildWindowList() { - return BuildWindowListInternal(NULL); +MruWindowTracker::WindowList MruWindowTracker::BuildMruWindowList() const { + return BuildWindowListInternal(&mru_windows_, + base::Bind(&ash::wm::CanActivateWindow)); } -MruWindowTracker::WindowList MruWindowTracker::BuildMruWindowList() { - return BuildWindowListInternal(&mru_windows_); +MruWindowTracker::WindowList +MruWindowTracker::BuildWindowListIgnoreModal() const { + return BuildWindowListInternal( + NULL, + base::Bind(&MruWindowTracker::IsWindowConsideredActivateable, + base::Unretained(this))); } void MruWindowTracker::SetIgnoreActivations(bool ignore) { @@ -191,4 +205,9 @@ void MruWindowTracker::OnWindowDestroyed(aura::Window* window) { window->RemoveObserver(this); } +bool MruWindowTracker::IsWindowConsideredActivateable( + aura::Window* window) const { + return focus_rules_->IsWindowConsideredActivatable(window); +} + } // namespace ash diff --git a/ash/wm/mru_window_tracker.h b/ash/wm/mru_window_tracker.h index 4ed06a3..f32f708 100644 --- a/ash/wm/mru_window_tracker.h +++ b/ash/wm/mru_window_tracker.h @@ -24,6 +24,13 @@ class ActivationClient; namespace ash { +namespace wm { + +class AshFocusRules; + +} // namespace wm + + // Maintains a most recently used list of windows. This is used for window // cycling using Alt+Tab and overview mode. class ASH_EXPORT MruWindowTracker @@ -32,21 +39,19 @@ class ASH_EXPORT MruWindowTracker public: typedef std::vector<aura::Window*> WindowList; - explicit MruWindowTracker( - aura::client::ActivationClient* activation_client); + MruWindowTracker( + aura::client::ActivationClient* activation_client, + ash::wm::AshFocusRules* focus_rules); ~MruWindowTracker() override; - // Returns the set of windows which can be cycled through. This method creates - // the vector based on the current set of windows across all valid root - // windows. As a result it is not necessarily the same as the set of - // windows being iterated over. - // The returned window list will be in descending (top most window first) - // order. - static WindowList BuildWindowList(); - // Returns the set of windows which can be cycled through using the tracked // list of most recently used windows. - WindowList BuildMruWindowList(); + WindowList BuildMruWindowList() const; + + // This does the same thing as the above, but ignores the system modal dialog + // state and hence the returned list could contain more windows if a system + // modal dialog window is present. + WindowList BuildWindowListIgnoreModal() const; // Starts or stops ignoring window activations. If no longer ignoring // activations the currently active window is moved to the front of the @@ -66,11 +71,17 @@ class ASH_EXPORT MruWindowTracker // Overridden from WindowObserver: void OnWindowDestroyed(aura::Window* window) override; + // Uses the focus rules to check whether the window can be activateable, + // regardless of the state of the System modal dialog. + bool IsWindowConsideredActivateable(aura::Window* window) const; + // List of windows that have been activated in containers that we cycle // through, sorted by most recently used. std::list<aura::Window*> mru_windows_; - aura::client::ActivationClient* activation_client_; + aura::client::ActivationClient* activation_client_; // Not owned. + + wm::AshFocusRules* focus_rules_; // Not owned. bool ignore_window_activations_; diff --git a/ash/wm/window_positioner.cc b/ash/wm/window_positioner.cc index 880abd1..4e80ed8 100644 --- a/ash/wm/window_positioner.cc +++ b/ash/wm/window_positioner.cc @@ -191,8 +191,8 @@ aura::Window* GetReferenceWindow(const aura::Window* root_window, active = NULL; // Get a list of all windows. - const std::vector<aura::Window*> windows = - ash::MruWindowTracker::BuildWindowList(); + const std::vector<aura::Window*> windows = ash::Shell::GetInstance()-> + mru_window_tracker()->BuildWindowListIgnoreModal(); if (windows.empty()) return NULL; @@ -503,8 +503,8 @@ gfx::Rect WindowPositioner::SmartPopupPosition( const gfx::Rect& old_pos, const gfx::Rect& work_area, int grid) { - const std::vector<aura::Window*> windows = - MruWindowTracker::BuildWindowList(); + const std::vector<aura::Window*> windows = ash::Shell::GetInstance()-> + mru_window_tracker()->BuildWindowListIgnoreModal(); std::vector<const gfx::Rect*> regions; // Process the window list and check if we can bail immediately. diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc index 564f044..1465a58 100644 --- a/chrome/browser/chromeos/extensions/wallpaper_private_api.cc +++ b/chrome/browser/chromeos/extensions/wallpaper_private_api.cc @@ -175,7 +175,8 @@ void WindowStateManager::BuildWindowListAndMinimizeInactiveForUser( std::set<aura::Window*>* results = &user_id_hash_window_list_map_[user_id_hash]; - std::vector<aura::Window*> windows = ash::MruWindowTracker::BuildWindowList(); + std::vector<aura::Window*> windows = ash::Shell::GetInstance()-> + mru_window_tracker()->BuildWindowListIgnoreModal(); for (std::vector<aura::Window*>::iterator iter = windows.begin(); iter != windows.end(); ++iter) { |