diff options
author | yoshiki@chromium.org <yoshiki@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-28 18:08:22 +0000 |
---|---|---|
committer | yoshiki@chromium.org <yoshiki@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-28 18:08:22 +0000 |
commit | 3ca185cdb039551e08443c671a5d3a78cbc6454c (patch) | |
tree | 94fd19dcffc7be74a4afbb262e430aa530d7fa4a | |
parent | c22c3bb135635b10393e263442159b96903fa7f1 (diff) | |
download | chromium_src-3ca185cdb039551e08443c671a5d3a78cbc6454c.zip chromium_src-3ca185cdb039551e08443c671a5d3a78cbc6454c.tar.gz chromium_src-3ca185cdb039551e08443c671a5d3a78cbc6454c.tar.bz2 |
Aura: Add non-browser windows into the list of "Alt + Tab" cycle.
This CL changes to use the child window list of the default container as the list of "Alt + Tab" cycle, instead of the browsers' list. But the list excludes the window which is not forcusable and has modal window as a child.
This CL can enable us to focus task manager window with "Alt + Tab" switcher.
BUG=118611
TEST=manual
Review URL: http://codereview.chromium.org/9719037
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@129443 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ash/wm/activation_controller.cc | 27 | ||||
-rw-r--r-- | ash/wm/activation_controller.h | 1 | ||||
-rw-r--r-- | ash/wm/activation_controller_unittest.cc | 50 | ||||
-rw-r--r-- | ash/wm/window_util.cc | 9 | ||||
-rw-r--r-- | ash/wm/window_util.h | 1 | ||||
-rw-r--r-- | chrome/browser/ui/views/ash/chrome_shell_delegate.cc | 35 | ||||
-rw-r--r-- | ui/aura/client/activation_client.h | 4 | ||||
-rw-r--r-- | ui/aura/test/test_activation_client.cc | 4 | ||||
-rw-r--r-- | ui/aura/test/test_activation_client.h | 1 |
9 files changed, 107 insertions, 25 deletions
diff --git a/ash/wm/activation_controller.cc b/ash/wm/activation_controller.cc index 3ac9895..cfe74f5 100644 --- a/ash/wm/activation_controller.cc +++ b/ash/wm/activation_controller.cc @@ -55,10 +55,22 @@ bool SupportsChildActivation(aura::Window* window) { return false; } +bool HasModalTransientChild(aura::Window* window) { + aura::Window::Windows::const_iterator it; + for (it = window->transient_children().begin(); + it != window->transient_children().end(); + ++it) { + if ((*it)->GetProperty(aura::client::kModalKey) == ui::MODAL_TYPE_WINDOW) + return true; + } + return false; +} + // Returns true if |window| can be activated or deactivated. // A window manager typically defines some notion of "top level window" that // supports activation/deactivation. -bool CanActivateWindow(aura::Window* window, const aura::Event* event) { +bool CanActivateWindowWithEvent(aura::Window* window, + const aura::Event* event) { return window && (window->IsVisible() || wm::IsWindowMinimized(window)) && (!aura::client::GetActivationDelegate(window) || @@ -104,7 +116,7 @@ aura::Window* ActivationController::GetActivatableWindow( aura::Window* parent = window->parent(); aura::Window* child = window; while (parent) { - if (CanActivateWindow(child, event)) + if (CanActivateWindowWithEvent(child, event)) return child; // If |child| isn't activatable, but has transient parent, trace // that path instead. @@ -116,6 +128,11 @@ aura::Window* ActivationController::GetActivatableWindow( return NULL; } +bool ActivationController::CanActivateWindow(aura::Window* window) const { + return CanActivateWindowWithEvent(window, NULL) && + !HasModalTransientChild(window); +} + //////////////////////////////////////////////////////////////////////////////// // ActivationController, aura::client::ActivationClient implementation: @@ -135,7 +152,7 @@ aura::Window* ActivationController::GetActiveWindow() { bool ActivationController::OnWillFocusWindow(aura::Window* window, const aura::Event* event) { - return CanActivateWindow(GetActivatableWindow(window, event), event); + return CanActivateWindowWithEvent(GetActivatableWindow(window, event), event); } //////////////////////////////////////////////////////////////////////////////// @@ -202,7 +219,7 @@ void ActivationController::ActivateWindowWithEvent(aura::Window* window, return; // The stacking client may impose rules on what window configurations can be // activated or deactivated. - if (window && !CanActivateWindow(window, event)) + if (window && !CanActivateWindowWithEvent(window, event)) return; // Restore minimized window. This needs to be done before CanReceiveEvents() @@ -278,7 +295,7 @@ aura::Window* ActivationController::GetTopmostWindowToActivateInContainer( container->children().rbegin(); i != container->children().rend(); ++i) { - if (*i != ignore && CanActivateWindow(*i, NULL)) + if (*i != ignore && CanActivateWindowWithEvent(*i, NULL)) return *i; } return NULL; diff --git a/ash/wm/activation_controller.h b/ash/wm/activation_controller.h index df19a52..9494345 100644 --- a/ash/wm/activation_controller.h +++ b/ash/wm/activation_controller.h @@ -40,6 +40,7 @@ class ASH_EXPORT ActivationController virtual aura::Window* GetActiveWindow() OVERRIDE; virtual bool OnWillFocusWindow(aura::Window* window, const aura::Event* event) OVERRIDE; + virtual bool CanActivateWindow(aura::Window* window) const OVERRIDE; // Overridden from aura::WindowObserver: virtual void OnWindowVisibilityChanged(aura::Window* window, diff --git a/ash/wm/activation_controller_unittest.cc b/ash/wm/activation_controller_unittest.cc index 52cb9bb..65bc0ef 100644 --- a/ash/wm/activation_controller_unittest.cc +++ b/ash/wm/activation_controller_unittest.cc @@ -9,6 +9,7 @@ #include "ash/test/ash_test_base.h" #include "ash/test/test_activation_delegate.h" #include "ash/wm/window_util.h" +#include "ui/aura/client/aura_constants.h" #include "ui/aura/focus_manager.h" #include "ui/aura/root_window.h" #include "ui/aura/test/event_generator.h" @@ -318,7 +319,7 @@ TEST_F(ActivationControllerTest, PreventFocusToNonActivatableWindow) { aura::test::TestWindowDelegate wd; scoped_ptr<aura::Window> w1(aura::test::CreateTestWindowWithDelegate( &wd, -1, gfx::Rect(50, 50), NULL)); - // The RootWindow itself is a non-activatable parent. + // The RootWindow is a non-activatable parent. scoped_ptr<aura::Window> w2(aura::test::CreateTestWindowWithDelegate( &wd, -2, gfx::Rect(50, 50), Shell::GetRootWindow())); scoped_ptr<aura::Window> w21(aura::test::CreateTestWindowWithDelegate( @@ -350,6 +351,53 @@ TEST_F(ActivationControllerTest, PreventFocusToNonActivatableWindow) { EXPECT_TRUE(w1->HasFocus()); } +TEST_F(ActivationControllerTest, CanActivateWindowIteselfTest) +{ + aura::test::TestWindowDelegate wd; + + // Normal Window + scoped_ptr<aura::Window> w1(aura::test::CreateTestWindowWithDelegate( + &wd, -1, gfx::Rect(50, 50), NULL)); + EXPECT_TRUE(wm::CanActivateWindow(w1.get())); + + // The RootWindow is a non-activatable parent. + scoped_ptr<aura::Window> w2(aura::test::CreateTestWindowWithDelegate( + &wd, -2, gfx::Rect(50, 50), Shell::GetRootWindow())); + scoped_ptr<aura::Window> w21(aura::test::CreateTestWindowWithDelegate( + &wd, -21, gfx::Rect(50, 50), w2.get())); + EXPECT_FALSE(wm::CanActivateWindow(w2.get())); + EXPECT_FALSE(wm::CanActivateWindow(w21.get())); + + // The window has a transient child. + scoped_ptr<aura::Window> w3(aura::test::CreateTestWindowWithDelegate( + &wd, -3, gfx::Rect(50, 50), NULL)); + scoped_ptr<aura::Window> w31(aura::test::CreateTestWindowWithDelegate( + &wd, -31, gfx::Rect(50, 50), NULL)); + w3->AddTransientChild(w31.get()); + EXPECT_TRUE(wm::CanActivateWindow(w3.get())); + EXPECT_TRUE(wm::CanActivateWindow(w31.get())); + + // The window has a transient window-modal child. + scoped_ptr<aura::Window> w4(aura::test::CreateTestWindowWithDelegate( + &wd, -4, gfx::Rect(50, 50), NULL)); + scoped_ptr<aura::Window> w41(aura::test::CreateTestWindowWithDelegate( + &wd, -41, gfx::Rect(50, 50), NULL)); + w4->AddTransientChild(w41.get()); + w41->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW); + EXPECT_FALSE(wm::CanActivateWindow(w4.get())); + EXPECT_TRUE(wm::CanActivateWindow(w41.get())); + + // The window has a transient system-modal child. + scoped_ptr<aura::Window> w5(aura::test::CreateTestWindowWithDelegate( + &wd, -5, gfx::Rect(50, 50), NULL)); + scoped_ptr<aura::Window> w51(aura::test::CreateTestWindowWithDelegate( + &wd, -51, gfx::Rect(50, 50), NULL)); + w5->AddTransientChild(w51.get()); + w51->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_SYSTEM); + EXPECT_TRUE(wm::CanActivateWindow(w5.get())); + EXPECT_TRUE(wm::CanActivateWindow(w51.get())); +} + // Verifies code in ActivationController::OnWindowVisibilityChanged() that keeps // hiding windows layers stacked above the newly active window while they // animate away. diff --git a/ash/wm/window_util.cc b/ash/wm/window_util.cc index a6d15b4..be1f3e9 100644 --- a/ash/wm/window_util.cc +++ b/ash/wm/window_util.cc @@ -53,6 +53,15 @@ aura::Window* GetActivatableWindow(aura::Window* window) { return internal::ActivationController::GetActivatableWindow(window, NULL); } +bool CanActivateWindow(aura::Window* window) { + DCHECK(window); + if (!window->GetRootWindow()) + return false; + aura::client::ActivationClient* client = + aura::client::GetActivationClient(window->GetRootWindow()); + return client && client->CanActivateWindow(window); +} + bool IsWindowNormal(aura::Window* window) { return window->GetProperty(aura::client::kShowStateKey) == ui::SHOW_STATE_NORMAL || diff --git a/ash/wm/window_util.h b/ash/wm/window_util.h index d0d11d2..c4da88b 100644 --- a/ash/wm/window_util.h +++ b/ash/wm/window_util.h @@ -20,6 +20,7 @@ ASH_EXPORT void ActivateWindow(aura::Window* window); ASH_EXPORT void DeactivateWindow(aura::Window* window); ASH_EXPORT bool IsActiveWindow(aura::Window* window); ASH_EXPORT aura::Window* GetActiveWindow(); +ASH_EXPORT bool CanActivateWindow(aura::Window* window); // Retrieves the activatable window for |window|. If |window| is activatable, // this will just return it, otherwise it will climb the parent/transient parent diff --git a/chrome/browser/ui/views/ash/chrome_shell_delegate.cc b/chrome/browser/ui/views/ash/chrome_shell_delegate.cc index e31ca99..af6184c 100644 --- a/chrome/browser/ui/views/ash/chrome_shell_delegate.cc +++ b/chrome/browser/ui/views/ash/chrome_shell_delegate.cc @@ -4,7 +4,10 @@ #include "chrome/browser/ui/views/ash/chrome_shell_delegate.h" +#include <algorithm> + #include "ash/launcher/launcher_types.h" +#include "ash/shell_window_ids.h" #include "ash/system/tray/system_tray_delegate.h" #include "ash/wm/partial_screenshot_view.h" #include "ash/wm/window_util.h" @@ -32,22 +35,6 @@ #include "chrome/browser/chromeos/login/user_manager.h" #include "chrome/browser/chromeos/system/ash_system_tray_delegate.h" #endif -namespace { - -// Returns a list of Aura windows from a BrowserList, using either a -// const_iterator or const_reverse_iterator. -template<typename IT> -std::vector<aura::Window*> GetBrowserWindows(IT begin, IT end) { - std::vector<aura::Window*> windows; - for (IT it = begin; it != end; ++it) { - Browser* browser = *it; - if (browser && browser->window()->GetNativeHandle()) - windows.push_back(browser->window()->GetNativeHandle()); - } - return windows; -} - -} // namespace // static ChromeShellDelegate* ChromeShellDelegate::instance_ = NULL; @@ -135,9 +122,19 @@ ChromeShellDelegate::CreateAppListViewDelegate() { std::vector<aura::Window*> ChromeShellDelegate::GetCycleWindowList( CycleSource source) const { - // BrowserList maintains a list of browsers sorted by activity. - return GetBrowserWindows(BrowserList::begin_last_active(), - BrowserList::end_last_active()); + aura::Window* default_container = ash::Shell::GetInstance()->GetContainer( + ash::internal::kShellWindowId_DefaultContainer); + std::vector<aura::Window*> windows = default_container->children(); + // Removes unforcusable windows. + std::vector<aura::Window*>::iterator last = + std::remove_if( + windows.begin(), + windows.end(), + std::not1(std::ptr_fun(ash::wm::CanActivateWindow))); + windows.erase(last, windows.end()); + // Window cycling expects the topmost window at the front of the list. + std::reverse(windows.begin(), windows.end()); + return windows; } void ChromeShellDelegate::StartPartialScreenshot( diff --git a/ui/aura/client/activation_client.h b/ui/aura/client/activation_client.h index 0c33258..7996a05 100644 --- a/ui/aura/client/activation_client.h +++ b/ui/aura/client/activation_client.h @@ -33,6 +33,10 @@ class AURA_EXPORT ActivationClient { // may be NULL. Returning false blocks |window| from getting focus. virtual bool OnWillFocusWindow(Window* window, const Event* event) = 0; + // Returns true if |window| can be activated, false otherwise. If |window| has + // a modal child it can not be activated. + virtual bool CanActivateWindow(Window* window) const = 0; + protected: virtual ~ActivationClient() {} }; diff --git a/ui/aura/test/test_activation_client.cc b/ui/aura/test/test_activation_client.cc index 114bf91..66c7511 100644 --- a/ui/aura/test/test_activation_client.cc +++ b/ui/aura/test/test_activation_client.cc @@ -59,6 +59,10 @@ bool TestActivationClient::OnWillFocusWindow(Window* window, return true; } +bool TestActivationClient::CanActivateWindow(Window* window) const { + return true; +} + //////////////////////////////////////////////////////////////////////////////// // TestActivationClient, WindowObserver implementation: diff --git a/ui/aura/test/test_activation_client.h b/ui/aura/test/test_activation_client.h index cd91c3b..c7e9809 100644 --- a/ui/aura/test/test_activation_client.h +++ b/ui/aura/test/test_activation_client.h @@ -26,6 +26,7 @@ class TestActivationClient : public client::ActivationClient, virtual void DeactivateWindow(Window* window) OVERRIDE; virtual Window* GetActiveWindow() OVERRIDE; virtual bool OnWillFocusWindow(Window* window, const Event* event) OVERRIDE; + virtual bool CanActivateWindow(Window* window) const OVERRIDE; // Overridden from WindowObserver: virtual void OnWindowDestroyed(Window* window) OVERRIDE; |