summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-01 11:45:29 +0000
committeroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-01 11:45:29 +0000
commitb42910f2a08d5eb08015f202c18bb05af1575125 (patch)
tree61b4c0ef2390fab101fa8d2f0f47a48ef77d2c45
parent44ea8c724f68466ba84a574540f799085b69871e (diff)
downloadchromium_src-b42910f2a08d5eb08015f202c18bb05af1575125.zip
chromium_src-b42910f2a08d5eb08015f202c18bb05af1575125.tar.gz
chromium_src-b42910f2a08d5eb08015f202c18bb05af1575125.tar.bz2
open new window in the same root window where the launcher was in
* Introduced ScopedRootWindowActivator to temporarily switch active root window. BUG=241571 TEST=covered by test Review URL: https://chromiumcodereview.appspot.com/19945008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@215000 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ash/ash.gyp2
-rw-r--r--ash/launcher/launcher_view.cc6
-rw-r--r--ash/scoped_target_root_window.cc21
-rw-r--r--ash/scoped_target_root_window.h33
-rw-r--r--ash/shell.cc18
-rw-r--r--ash/shell.h24
-rw-r--r--chrome/browser/ui/window_sizer/window_sizer_ash.cc14
-rw-r--r--chrome/browser/ui/window_sizer/window_sizer_ash_uitest.cc199
-rw-r--r--chrome/chrome_tests.gypi1
9 files changed, 291 insertions, 27 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp
index 29a3c38..dc8ee39 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -175,6 +175,8 @@
'root_window_controller.h',
'rotator/screen_rotation.cc',
'rotator/screen_rotation.h',
+ 'scoped_target_root_window.cc',
+ 'scoped_target_root_window.h',
'screen_ash.cc',
'screen_ash.h',
'screensaver/screensaver_view.cc',
diff --git a/ash/launcher/launcher_view.cc b/ash/launcher/launcher_view.cc
index ede55d4..015ba3f 100644
--- a/ash/launcher/launcher_view.cc
+++ b/ash/launcher/launcher_view.cc
@@ -20,6 +20,7 @@
#include "ash/launcher/overflow_button.h"
#include "ash/launcher/tabbed_launcher_button.h"
#include "ash/root_window_controller.h"
+#include "ash/scoped_target_root_window.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell_delegate.h"
@@ -1496,6 +1497,8 @@ void LauncherView::ButtonPressed(views::Button* sender,
return;
{
+ ScopedTargetRootWindow scoped_target(
+ sender->GetWidget()->GetNativeView()->GetRootWindow());
// Slow down activation animations if shift key is pressed.
scoped_ptr<ui::ScopedAnimationDurationScaleMode> slowing_animations;
if (event.IsShiftDown()) {
@@ -1596,6 +1599,9 @@ void LauncherView::ShowMenu(
launcher_menu_runner_.reset(
new views::MenuRunner(menu_model_adapter->CreateMenu()));
+ ScopedTargetRootWindow scoped_target(
+ source->GetWidget()->GetNativeView()->GetRootWindow());
+
// Determine the menu alignment dependent on the shelf.
views::MenuItemView::AnchorPosition menu_alignment =
views::MenuItemView::TOPLEFT;
diff --git a/ash/scoped_target_root_window.cc b/ash/scoped_target_root_window.cc
new file mode 100644
index 0000000..b488a6f
--- /dev/null
+++ b/ash/scoped_target_root_window.cc
@@ -0,0 +1,21 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "ash/scoped_target_root_window.h"
+
+#include "ash/shell.h"
+
+namespace ash {
+namespace internal {
+
+ScopedTargetRootWindow::ScopedTargetRootWindow(
+ aura::RootWindow* root_window) {
+ Shell::GetInstance()->scoped_target_root_window_ = root_window;
+}
+
+ScopedTargetRootWindow::~ScopedTargetRootWindow() {
+ Shell::GetInstance()->scoped_target_root_window_ = NULL;
+}
+
+} // namespace internal
+} // namespace ash
diff --git a/ash/scoped_target_root_window.h b/ash/scoped_target_root_window.h
new file mode 100644
index 0000000..ab695be
--- /dev/null
+++ b/ash/scoped_target_root_window.h
@@ -0,0 +1,33 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef ASH_SCOPED_TARGET_ROOT_WINDOW_H_
+#define ASH_SCOPED_TARGET_ROOT_WINDOW_H_
+
+#include "base/basictypes.h"
+
+namespace aura {
+class RootWindow;
+}
+
+namespace ash {
+namespace internal {
+
+// Constructing a ScopedTargetRootWindow allows temporarily
+// switching a target root window so that a new window gets created
+// in the same window where a user interaction happened.
+// An example usage is to specify the target root window when creating
+// a new window using launcher's icon.
+class ScopedTargetRootWindow {
+ public:
+ explicit ScopedTargetRootWindow(aura::RootWindow* root_window);
+ ~ScopedTargetRootWindow();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScopedTargetRootWindow);
+};
+
+} // namespace internal
+} // namespace ash
+
+#endif // ASH_SCOPED_TARGET_ROOT_WINDOW_H_
diff --git a/ash/shell.cc b/ash/shell.cc
index 1cf22a4..818b309 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -201,7 +201,8 @@ bool Shell::initially_hide_cursor_ = false;
Shell::Shell(ShellDelegate* delegate)
: screen_(new ScreenAsh),
- active_root_window_(NULL),
+ target_root_window_(NULL),
+ scoped_target_root_window_(NULL),
delegate_(delegate),
activation_client_(NULL),
#if defined(OS_CHROMEOS) && defined(USE_X11)
@@ -249,8 +250,7 @@ Shell::~Shell() {
// Remove the focus from any window. This will prevent overhead and side
// effects (e.g. crashes) from changing focus during shutdown.
// See bug crbug.com/134502.
- if (active_root_window_)
- aura::client::GetFocusClient(active_root_window_)->FocusWindow(NULL);
+ aura::client::GetFocusClient(GetPrimaryRootWindow())->FocusWindow(NULL);
// Please keep in same order as in Init() because it's easy to miss one.
RemovePreTargetHandler(event_rewriter_filter_.get());
@@ -386,7 +386,10 @@ aura::RootWindow* Shell::GetPrimaryRootWindow() {
// static
aura::RootWindow* Shell::GetActiveRootWindow() {
- return GetInstance()->active_root_window_;
+ Shell* shell = GetInstance();
+ if (shell->scoped_target_root_window_)
+ return shell->scoped_target_root_window_;
+ return shell->target_root_window_;
}
// static
@@ -499,7 +502,7 @@ void Shell::Init() {
display_controller_->Start();
display_controller_->InitPrimaryDisplay();
aura::RootWindow* root_window = display_controller_->GetPrimaryRootWindow();
- active_root_window_ = root_window;
+ target_root_window_ = root_window;
cursor_manager_.SetDisplay(DisplayController::GetPrimaryDisplay());
@@ -883,7 +886,8 @@ void Shell::InitRootWindowForSecondaryDisplay(aura::RootWindow* root) {
high_contrast_controller_->OnRootWindowAdded(root);
root->ShowRootWindow();
// Activate new root for testing.
- active_root_window_ = root;
+ // TODO(oshima): remove this.
+ target_root_window_ = root;
// Create a launcher if a user is already logged.
if (Shell::GetInstance()->session_state_delegate()->NumberOfLoggedInUsers())
@@ -970,7 +974,7 @@ void Shell::OnEvent(ui::Event* event) {
void Shell::OnWindowActivated(aura::Window* gained_active,
aura::Window* lost_active) {
if (gained_active)
- active_root_window_ = gained_active->GetRootWindow();
+ target_root_window_ = gained_active->GetRootWindow();
}
} // namespace ash
diff --git a/ash/shell.h b/ash/shell.h
index c2c1303..b6c669c 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -119,6 +119,7 @@ class OverlayEventFilter;
class ResizeShadowController;
class RootWindowController;
class RootWindowLayoutManager;
+class ScopedTargetRootWindow;
class ScreenPositionController;
class SlowAnimationEventFilter;
class StatusAreaWidget;
@@ -178,10 +179,12 @@ class ASH_EXPORT Shell
// that has a launcher.
static aura::RootWindow* GetPrimaryRootWindow();
- // Returns the active RootWindow. The active RootWindow is the one that
- // contains the current active window as a decendant child. The active
- // RootWindow remains the same even when the active window becomes NULL,
- // until the another window who has a different root window becomes active.
+ // Returns a RootWindow when used as a target when creating a new window.
+ // The root window of the active window is used in most cases, but can
+ // be overridden by using ScopedTargetRootWindow().
+ // If you want to get a RootWindow of the active window, just use
+ // |wm::GetActiveWindow()->GetRootWindow()|.
+ // TODO(oshima): Rename to GetTargetRootWindow() crbug.com/266378.
static aura::RootWindow* GetActiveRootWindow();
// Returns the global Screen object that's always active in ash.
@@ -206,8 +209,8 @@ class ASH_EXPORT Shell
// application windows to be maximized only.
static bool IsForcedMaximizeMode();
- void set_active_root_window(aura::RootWindow* active_root_window) {
- active_root_window_ = active_root_window;
+ void set_active_root_window(aura::RootWindow* target_root_window) {
+ target_root_window_ = target_root_window;
}
// Shows the context menu for the background and launcher at
@@ -473,6 +476,7 @@ class ASH_EXPORT Shell
FRIEND_TEST_ALL_PREFIXES(WindowManagerTest, MouseEventCursors);
FRIEND_TEST_ALL_PREFIXES(WindowManagerTest, TransformActivate);
friend class internal::RootWindowController;
+ friend class internal::ScopedTargetRootWindow;
friend class test::ShellTestApi;
friend class shell::WindowWatcher;
@@ -510,8 +514,12 @@ class ASH_EXPORT Shell
ScreenAsh* screen_;
- // Active root window. Never becomes NULL during the session.
- aura::RootWindow* active_root_window_;
+ // When no explicit target display/RootWindow is given, new windows are
+ // created on |scoped_target_root_window_| , unless NULL in
+ // which case they are created on |target_root_window_|.
+ // |target_root_window_| never becomes NULL during the session.
+ aura::RootWindow* target_root_window_;
+ aura::RootWindow* scoped_target_root_window_;
// The CompoundEventFilter owned by aura::Env object.
scoped_ptr<views::corewm::CompoundEventFilter> env_filter_;
diff --git a/chrome/browser/ui/window_sizer/window_sizer_ash.cc b/chrome/browser/ui/window_sizer/window_sizer_ash.cc
index 4537423..a4ee1d1 100644
--- a/chrome/browser/ui/window_sizer/window_sizer_ash.cc
+++ b/chrome/browser/ui/window_sizer/window_sizer_ash.cc
@@ -135,15 +135,6 @@ bool MoveRect(const gfx::Rect& work_area,
return false;
}
-// Adjust the |target_in_screen| rectangle so it moves as much as possible into
-// the |work_area| .
-void AdjustTargetRectVerticallyAgainstWorkspace(const gfx::Rect& work_area,
- gfx::Rect* target_in_screen) {
- if (target_in_screen->bottom() > work_area.bottom())
- target_in_screen->set_y(std::max(work_area.y(),
- work_area.bottom() - target_in_screen->height()));
-}
-
} // namespace
// static
@@ -205,8 +196,7 @@ bool WindowSizer::GetBoundsOverrideAsh(gfx::Rect* bounds_in_screen,
if ((!count || !top_window)) {
if (has_saved_bounds) {
// Restore to previous state - if there is one.
- AdjustTargetRectVerticallyAgainstWorkspace(work_area,
- bounds_in_screen);
+ bounds_in_screen->AdjustToFit(work_area);
return true;
}
// When using "small screens" we want to always open in full screen mode.
@@ -239,7 +229,7 @@ bool WindowSizer::GetBoundsOverrideAsh(gfx::Rect* bounds_in_screen,
bounds_in_screen->CenterPoint().x() < work_area.CenterPoint().x();
MoveRect(work_area, *bounds_in_screen, move_right);
- AdjustTargetRectVerticallyAgainstWorkspace(work_area, bounds_in_screen);
+ bounds_in_screen->AdjustToFit(work_area);
return true;
}
diff --git a/chrome/browser/ui/window_sizer/window_sizer_ash_uitest.cc b/chrome/browser/ui/window_sizer/window_sizer_ash_uitest.cc
new file mode 100644
index 0000000..61f702d
--- /dev/null
+++ b/chrome/browser/ui/window_sizer/window_sizer_ash_uitest.cc
@@ -0,0 +1,199 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/launcher/launcher.h"
+#include "ash/launcher/launcher_view.h"
+#include "ash/shell.h"
+#include "base/command_line.h"
+#include "base/message_loop/message_loop.h"
+#include "chrome/browser/lifetime/application_lifetime.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "ui/aura/root_window.h"
+#include "ui/aura/test/event_generator.h"
+#include "ui/base/test/ui_controls.h"
+#include "ui/views/controls/menu/menu_controller.h"
+#include "ui/views/view.h"
+#include "ui/views/view_model.h"
+
+namespace {
+
+class WindowSizerTest : public InProcessBrowserTest {
+ public:
+ WindowSizerTest() {}
+ virtual ~WindowSizerTest() {}
+
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ InProcessBrowserTest::SetUpCommandLine(command_line);
+ // Make screens sufficiently wide to host 2 browsers side by side.
+ command_line->AppendSwitchASCII("ash-host-window-bounds",
+ "600x600,601+0-600x600");
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WindowSizerTest);
+};
+
+void CloseBrowser(Browser* browser) {
+ browser->window()->Close();
+ base::MessageLoop::current()->RunUntilIdle();
+}
+
+gfx::Rect GetChromeIconBoundsForRootWindow(aura::RootWindow* root_window) {
+ ash::Launcher* launcher = ash::Launcher::ForWindow(root_window);
+ const ash::internal::LauncherView* launcher_view =
+ launcher->GetLauncherViewForTest();
+ const views::ViewModel* view_model = launcher_view->view_model_for_test();
+
+ EXPECT_EQ(2, view_model->view_size());
+ return view_model->view_at(0)->GetBoundsInScreen();
+}
+
+void OpenBrowserUsingShelfOnRootWindow(aura::RootWindow* root_window) {
+ aura::test::EventGenerator generator(root_window);
+ gfx::Point center =
+ GetChromeIconBoundsForRootWindow(root_window).CenterPoint();
+ gfx::Display display =
+ ash::Shell::GetScreen()->GetDisplayNearestWindow(root_window);
+ const gfx::Point& origin = display.bounds().origin();
+ center.Offset(- origin.x(), - origin.y());
+ generator.MoveMouseTo(center);
+ generator.ClickLeftButton();
+}
+
+} // namespace
+
+#if defined(OS_WIN)
+#define MAYBE_OpenBrowserUsingShelfOnOhterDisplay DISABLED_OpenBrowserUsingShelfOnOhterDisplay
+#define MAYBE_OpenBrowserUsingContextMenuOnOhterDisplay DISABLED_OpenBrowserUsingContextMenuOnOhterDisplay
+#else
+#define MAYBE_OpenBrowserUsingShelfOnOhterDisplay OpenBrowserUsingShelfOnOhterDisplay
+#define MAYBE_OpenBrowserUsingContextMenuOnOhterDisplay OpenBrowserUsingContextMenuOnOhterDisplay
+#endif
+
+IN_PROC_BROWSER_TEST_F(WindowSizerTest,
+ MAYBE_OpenBrowserUsingShelfOnOhterDisplay) {
+ // Don't shutdown when closing the last browser window.
+ chrome::StartKeepAlive();
+
+ ash::Shell::RootWindowList root_windows = ash::Shell::GetAllRootWindows();
+
+ BrowserList* browser_list =
+ BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
+
+ EXPECT_EQ(1u, browser_list->size());
+ // Close the browser window so that clicking icon will create a new window.
+ CloseBrowser(browser_list->get(0));
+ EXPECT_EQ(0u, browser_list->size());
+ EXPECT_EQ(root_windows[0], ash::Shell::GetActiveRootWindow());
+
+ OpenBrowserUsingShelfOnRootWindow(root_windows[1]);
+
+ // A new browser must be created on 2nd display.
+ EXPECT_EQ(1u, browser_list->size());
+ EXPECT_EQ(root_windows[1],
+ browser_list->get(0)->window()->GetNativeWindow()->GetRootWindow());
+ EXPECT_EQ(root_windows[1], ash::Shell::GetActiveRootWindow());
+
+ // Close the browser window so that clicking icon will create a new window.
+ CloseBrowser(browser_list->get(0));
+ EXPECT_EQ(0u, browser_list->size());
+
+ OpenBrowserUsingShelfOnRootWindow(root_windows[0]);
+
+ // A new browser must be created on 1st display.
+ EXPECT_EQ(1u, browser_list->size());
+ EXPECT_EQ(root_windows[0],
+ browser_list->get(0)->window()->GetNativeWindow()->GetRootWindow());
+ EXPECT_EQ(root_windows[0], ash::Shell::GetActiveRootWindow());
+
+ // Balanced with the chrome::StartKeepAlive above.
+ chrome::EndKeepAlive();
+}
+
+namespace {
+
+class WindowSizerContextMenuTest : public WindowSizerTest {
+ public:
+ WindowSizerContextMenuTest() {}
+ virtual ~WindowSizerContextMenuTest() {}
+
+ static void Step1(gfx::Point release_point) {
+ ui_controls::SendMouseEventsNotifyWhenDone(
+ ui_controls::RIGHT, ui_controls::DOWN,
+ base::Bind(&WindowSizerContextMenuTest::Step2, release_point));
+ }
+
+ static void Step2(gfx::Point release_point) {
+ ui_controls::SendMouseMoveNotifyWhenDone(
+ release_point.x(), release_point.y(),
+ base::Bind(&WindowSizerContextMenuTest::Step3));
+ }
+
+ static void Step3() {
+ ui_controls::SendMouseEventsNotifyWhenDone(
+ ui_controls::RIGHT, ui_controls::UP,
+ base::Bind(&WindowSizerContextMenuTest::QuitLoop));
+ }
+
+ static void QuitLoop() {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::MessageLoop::QuitWhenIdleClosure());
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WindowSizerContextMenuTest);
+};
+
+void OpenBrowserUsingContextMenuOnRootWindow(aura::RootWindow* root_window) {
+ gfx::Point chrome_icon =
+ GetChromeIconBoundsForRootWindow(root_window).CenterPoint();
+ gfx::Point release_point = chrome_icon;
+ release_point.Offset(50, -120);
+ ui_controls::SendMouseMoveNotifyWhenDone(
+ chrome_icon.x(), chrome_icon.y(),
+ base::Bind(&WindowSizerContextMenuTest::Step1, release_point));
+ base::MessageLoop::current()->Run();
+}
+
+} // namespace
+
+IN_PROC_BROWSER_TEST_F(WindowSizerContextMenuTest,
+ MAYBE_OpenBrowserUsingContextMenuOnOhterDisplay) {
+ // Don't shutdown when closing the last browser window.
+ chrome::StartKeepAlive();
+
+ views::MenuController::TurnOffContextMenuSelectionHoldForTest();
+
+ ash::Shell::RootWindowList root_windows = ash::Shell::GetAllRootWindows();
+
+ BrowserList* browser_list =
+ BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
+
+ EXPECT_EQ(1u, browser_list->size());
+ EXPECT_EQ(root_windows[0], ash::Shell::GetActiveRootWindow());
+ CloseBrowser(browser_list->get(0));
+
+ OpenBrowserUsingContextMenuOnRootWindow(root_windows[1]);
+
+ // A new browser must be created on 2nd display.
+ EXPECT_EQ(1u, browser_list->size());
+ EXPECT_EQ(root_windows[1],
+ browser_list->get(0)->window()->GetNativeWindow()->GetRootWindow());
+ EXPECT_EQ(root_windows[1], ash::Shell::GetActiveRootWindow());
+
+ OpenBrowserUsingContextMenuOnRootWindow(root_windows[0]);
+
+ // Next new browser must be created on 1st display.
+ EXPECT_EQ(2u, browser_list->size());
+ EXPECT_EQ(root_windows[0],
+ browser_list->get(1)->window()->GetNativeWindow()->GetRootWindow());
+ EXPECT_EQ(root_windows[0], ash::Shell::GetActiveRootWindow());
+
+ // Balanced with the chrome::StartKeepAlive above.
+ chrome::EndKeepAlive();
+}
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index ced2f88..0f9ef56 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -329,6 +329,7 @@
['use_ash==1', {
'sources': [
'../ash/drag_drop/drag_drop_interactive_uitest.cc',
+ 'browser/ui/window_sizer/window_sizer_ash_uitest.cc',
],
}],
['OS=="linux" and toolkit_views==1', {