Commit 3ca185cd authored by yoshiki@chromium.org's avatar yoshiki@chromium.org

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
parent c22c3bb1
......@@ -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;
......
......@@ -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,
......
......@@ -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.
......
......@@ -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 ||
......
......@@ -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
......
......@@ -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(
......
......@@ -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() {}
};
......
......@@ -59,6 +59,10 @@ bool TestActivationClient::OnWillFocusWindow(Window* window,
return true;
}
bool TestActivationClient::CanActivateWindow(Window* window) const {
return true;
}
////////////////////////////////////////////////////////////////////////////////
// TestActivationClient, WindowObserver implementation:
......
......@@ -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;
......
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