summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryoshiki@chromium.org <yoshiki@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-28 18:08:22 +0000
committeryoshiki@chromium.org <yoshiki@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-28 18:08:22 +0000
commit3ca185cdb039551e08443c671a5d3a78cbc6454c (patch)
tree94fd19dcffc7be74a4afbb262e430aa530d7fa4a
parentc22c3bb135635b10393e263442159b96903fa7f1 (diff)
downloadchromium_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.cc27
-rw-r--r--ash/wm/activation_controller.h1
-rw-r--r--ash/wm/activation_controller_unittest.cc50
-rw-r--r--ash/wm/window_util.cc9
-rw-r--r--ash/wm/window_util.h1
-rw-r--r--chrome/browser/ui/views/ash/chrome_shell_delegate.cc35
-rw-r--r--ui/aura/client/activation_client.h4
-rw-r--r--ui/aura/test/test_activation_client.cc4
-rw-r--r--ui/aura/test/test_activation_client.h1
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;