summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ash/accelerators/accelerator_controller.cc37
-rw-r--r--ash/accelerators/accelerator_table.cc4
-rw-r--r--ash/accelerators/accelerator_table.h2
-rw-r--r--ash/display/display_controller.cc44
-rw-r--r--ash/display/display_controller.h20
-rw-r--r--ash/display/display_controller_unittest.cc40
-rw-r--r--ash/display/multi_display_manager.cc32
-rw-r--r--ash/display/multi_display_manager.h2
-rw-r--r--ash/display/multi_display_manager_unittest.cc17
-rw-r--r--ash/root_window_controller.cc13
-rw-r--r--ash/root_window_controller.h6
-rw-r--r--ash/ui_controls_ash.cc50
-rw-r--r--ash/wm/toplevel_window_event_filter.cc21
-rw-r--r--ash/wm/toplevel_window_event_filter.h16
-rw-r--r--ash/wm/toplevel_window_event_filter_unittest.cc4
-rw-r--r--ash/wm/workspace/workspace_window_resizer_unittest.cc18
-rw-r--r--chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc151
-rw-r--r--ui/aura/client/window_move_client.h10
-rw-r--r--ui/aura/root_window.cc6
-rw-r--r--ui/aura/root_window.h3
-rw-r--r--ui/aura/root_window_host.h3
-rw-r--r--ui/aura/root_window_host_linux.cc4
-rw-r--r--ui/aura/root_window_host_linux.h1
-rw-r--r--ui/aura/root_window_host_win.cc4
-rw-r--r--ui/aura/root_window_host_win.h1
-rw-r--r--ui/views/widget/desktop_root_window_host_win.cc3
-rw-r--r--ui/views/widget/desktop_root_window_host_win.h1
-rw-r--r--ui/views/widget/native_widget_aura.cc7
-rw-r--r--ui/views/widget/x11_desktop_window_move_client.cc8
-rw-r--r--ui/views/widget/x11_desktop_window_move_client.h5
30 files changed, 410 insertions, 123 deletions
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc
index 63b86e1..199ee16 100644
--- a/ash/accelerators/accelerator_controller.cc
+++ b/ash/accelerators/accelerator_controller.cc
@@ -53,6 +53,7 @@
#if defined(OS_CHROMEOS)
#include "ash/display/output_configurator_animation.h"
+#include "base/chromeos/chromeos_version.h"
#include "chromeos/display/output_configurator.h"
#endif // defined(OS_CHROMEOS)
@@ -105,7 +106,20 @@ bool HandleToggleSpokenFeedback() {
Shell::GetInstance()->delegate()->ToggleSpokenFeedback();
return true;
}
-#endif
+void HandleCycleDisplayMode() {
+ Shell* shell = Shell::GetInstance();
+ if (!base::chromeos::IsRunningOnChromeOS()) {
+ internal::MultiDisplayManager::CycleDisplay();
+ } else if (shell->output_configurator()->connected_output_count() > 1) {
+ internal::OutputConfiguratorAnimation* animation =
+ shell->output_configurator_animation();
+ animation->StartFadeOutAnimation(base::Bind(
+ base::IgnoreResult(&chromeos::OutputConfigurator::CycleDisplayMode),
+ base::Unretained(shell->output_configurator())));
+ }
+}
+
+#endif // defined(OS_CHROMEOS)
bool HandleExit() {
ShellDelegate* delegate = Shell::GetInstance()->delegate();
@@ -440,18 +454,9 @@ bool AcceleratorController::PerformAction(int action,
if (Shell::GetInstance()->tray_delegate())
Shell::GetInstance()->tray_delegate()->ToggleWifi();
return true;
- case CYCLE_DISPLAY_MODE: {
- Shell* shell = Shell::GetInstance();
- if (shell->output_configurator()->connected_output_count() > 1) {
- internal::OutputConfiguratorAnimation* animation =
- shell->output_configurator_animation();
- animation->StartFadeOutAnimation(base::Bind(
- base::IgnoreResult(&chromeos::OutputConfigurator::CycleDisplayMode),
- base::Unretained(shell->output_configurator())));
- return true;
- }
- return false;
- }
+ case CYCLE_DISPLAY_MODE:
+ HandleCycleDisplayMode();
+ return true;
#endif
case OPEN_FEEDBACK_PAGE:
ash::Shell::GetInstance()->delegate()->OpenFeedbackPage();
@@ -675,12 +680,6 @@ bool AcceleratorController::PerformAction(int action,
return HandleToggleDesktopBackgroundMode();
case TOGGLE_ROOT_WINDOW_FULL_SCREEN:
return HandleToggleRootWindowFullScreen();
- case DISPLAY_ADD_REMOVE:
- internal::MultiDisplayManager::AddRemoveDisplay();
- return true;
- case DISPLAY_CYCLE:
- internal::MultiDisplayManager::CycleDisplay();
- return true;
case DISPLAY_TOGGLE_SCALE:
internal::MultiDisplayManager::ToggleDisplayScale();
return true;
diff --git a/ash/accelerators/accelerator_table.cc b/ash/accelerators/accelerator_table.cc
index 7b4d036..e7bfcc0 100644
--- a/ash/accelerators/accelerator_table.cc
+++ b/ash/accelerators/accelerator_table.cc
@@ -147,8 +147,6 @@ const AcceleratorData kDebugAcceleratorData[] = {
// For testing on systems where Alt-Tab is already mapped.
{ true, ui::VKEY_W, ui::EF_ALT_DOWN, CYCLE_FORWARD_MRU },
{ true, ui::VKEY_W, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, CYCLE_BACKWARD_MRU },
- { true, ui::VKEY_F4, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, DISPLAY_CYCLE },
- { true, ui::VKEY_F4, ui::EF_SHIFT_DOWN, DISPLAY_ADD_REMOVE },
{ true, ui::VKEY_HOME, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
DISPLAY_TOGGLE_SCALE },
#if !defined(NDEBUG)
@@ -173,8 +171,6 @@ const AcceleratorAction kReservedActions[] = {
FOCUS_PREVIOUS_PANE, // Control+F1
FOCUS_NEXT_PANE, // Control+F2
CYCLE_DISPLAY_MODE, // Control+F4
- DISPLAY_ADD_REMOVE, // Shift+F4
- DISPLAY_CYCLE, // Shift+Control+F4
CYCLE_FORWARD_LINEAR, // F5
CYCLE_BACKWARD_LINEAR, // Shift+F5
TAKE_SCREENSHOT, // Control+F5
diff --git a/ash/accelerators/accelerator_table.h b/ash/accelerators/accelerator_table.h
index 3469244..4f2b867 100644
--- a/ash/accelerators/accelerator_table.h
+++ b/ash/accelerators/accelerator_table.h
@@ -20,8 +20,6 @@ enum AcceleratorAction {
CYCLE_FORWARD_LINEAR,
CYCLE_FORWARD_MRU,
DISABLE_CAPS_LOCK,
- DISPLAY_ADD_REMOVE,
- DISPLAY_CYCLE,
DISPLAY_TOGGLE_SCALE,
EXIT,
FOCUS_LAUNCHER,
diff --git a/ash/display/display_controller.cc b/ash/display/display_controller.cc
index 16ee88c..5cc96e7 100644
--- a/ash/display/display_controller.cc
+++ b/ash/display/display_controller.cc
@@ -180,6 +180,14 @@ void DisplayController::InitSecondaryDisplays() {
UpdateDisplayBoundsForLayout();
}
+void DisplayController::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void DisplayController::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
aura::RootWindow* DisplayController::GetPrimaryRootWindow() {
DCHECK(!root_windows_.empty());
aura::DisplayManager* display_manager =
@@ -233,14 +241,23 @@ DisplayController::GetAllRootWindowControllers() {
}
void DisplayController::SetDefaultDisplayLayout(const DisplayLayout& layout) {
- default_display_layout_ = layout;
- UpdateDisplayBoundsForLayout();
+ if (default_display_layout_.position != layout.position ||
+ default_display_layout_.offset != layout.offset) {
+ default_display_layout_ = layout;
+ NotifyDisplayConfigurationChanging();
+ UpdateDisplayBoundsForLayout();
+ }
}
void DisplayController::SetLayoutForDisplayName(const std::string& name,
const DisplayLayout& layout) {
- secondary_layouts_[name] = layout;
- UpdateDisplayBoundsForLayout();
+ DisplayLayout& display_for_name = secondary_layouts_[name];
+ if (display_for_name.position != layout.position ||
+ display_for_name.offset != layout.offset) {
+ secondary_layouts_[name] = layout;
+ NotifyDisplayConfigurationChanging();
+ UpdateDisplayBoundsForLayout();
+ }
}
const DisplayLayout& DisplayController::GetLayoutForDisplayName(
@@ -254,12 +271,14 @@ const DisplayLayout& DisplayController::GetLayoutForDisplayName(
}
void DisplayController::OnDisplayBoundsChanged(const gfx::Display& display) {
+ NotifyDisplayConfigurationChanging();
root_windows_[display.id()]->SetHostBounds(display.bounds_in_pixel());
UpdateDisplayBoundsForLayout();
}
void DisplayController::OnDisplayAdded(const gfx::Display& display) {
DCHECK(!root_windows_.empty());
+ NotifyDisplayConfigurationChanging();
aura::RootWindow* root = AddRootWindowForDisplay(display);
Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root);
UpdateDisplayBoundsForLayout();
@@ -270,18 +289,19 @@ void DisplayController::OnDisplayRemoved(const gfx::Display& display) {
DCHECK(root);
// Primary display should never be removed by DisplayManager.
DCHECK(root != GetPrimaryRootWindow());
+ NotifyDisplayConfigurationChanging();
// Display for root window will be deleted when the Primary RootWindow
// is deleted by the Shell.
if (root != GetPrimaryRootWindow()) {
root_windows_.erase(display.id());
internal::RootWindowController* controller =
GetRootWindowController(root);
- if (controller) {
- controller->MoveWindowsTo(GetPrimaryRootWindow());
- delete controller;
- } else {
- delete root;
- }
+ DCHECK(controller);
+ controller->MoveWindowsTo(GetPrimaryRootWindow());
+ // Delete most of root window related objects, but don't delete
+ // root window itself yet because the stak may be using it.
+ controller->Shutdown();
+ MessageLoop::current()->DeleteSoon(FROM_HERE, controller);
}
}
@@ -357,4 +377,8 @@ void DisplayController::UpdateDisplayBoundsForLayout() {
secondary_display->UpdateWorkAreaFromInsets(insets);
}
+void DisplayController::NotifyDisplayConfigurationChanging() {
+ FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanging());
+}
+
} // namespace ash
diff --git a/ash/display/display_controller.h b/ash/display/display_controller.h
index d6e122e..661ce13 100644
--- a/ash/display/display_controller.h
+++ b/ash/display/display_controller.h
@@ -11,6 +11,8 @@
#include "ash/ash_export.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
+#include "base/observer_list.h"
#include "ui/aura/display_observer.h"
#include "ui/aura/display_manager.h"
@@ -61,6 +63,16 @@ struct ASH_EXPORT DisplayLayout {
// display, keeping them in sync with display configuration changes.
class ASH_EXPORT DisplayController : public aura::DisplayObserver {
public:
+ class Observer {
+ public:
+ // Invoked when the display configuration change is requested,
+ // but before the change is applied to aura/ash.
+ virtual void OnDisplayConfigurationChanging() = 0;
+
+ protected:
+ virtual ~Observer() {}
+ };
+
DisplayController();
virtual ~DisplayController();
@@ -70,6 +82,10 @@ class ASH_EXPORT DisplayController : public aura::DisplayObserver {
// Initialize secondary displays.
void InitSecondaryDisplays();
+ // Add/Remove observers.
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
// Returns the root window for primary display.
aura::RootWindow* GetPrimaryRootWindow();
@@ -111,6 +127,8 @@ class ASH_EXPORT DisplayController : public aura::DisplayObserver {
void UpdateDisplayBoundsForLayout();
+ void NotifyDisplayConfigurationChanging();
+
// The mapping from display ID to its root window.
std::map<int64, aura::RootWindow*> root_windows_;
@@ -120,6 +138,8 @@ class ASH_EXPORT DisplayController : public aura::DisplayObserver {
// Per-device display layout.
std::map<std::string, DisplayLayout> secondary_layouts_;
+ ObserverList<Observer> observers_;
+
DISALLOW_COPY_AND_ASSIGN(DisplayController);
};
diff --git a/ash/display/display_controller_unittest.cc b/ash/display/display_controller_unittest.cc
index 428d0de..d2be5b6 100644
--- a/ash/display/display_controller_unittest.cc
+++ b/ash/display/display_controller_unittest.cc
@@ -16,6 +16,32 @@ namespace ash {
namespace test {
namespace {
+class TestObserver : public DisplayController::Observer {
+ public:
+ TestObserver() : count_(0) {
+ Shell::GetInstance()->display_controller()->AddObserver(this);
+ }
+
+ virtual ~TestObserver() {
+ Shell::GetInstance()->display_controller()->RemoveObserver(this);
+ }
+
+ virtual void OnDisplayConfigurationChanging() OVERRIDE {
+ ++count_;
+ }
+
+ int CountAndReset() {
+ int c = count_;
+ count_ = 0;
+ return c;
+ }
+
+ private:
+ int count_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestObserver);
+};
+
gfx::Display GetPrimaryDisplay() {
return gfx::Screen::GetDisplayNearestWindow(
Shell::GetAllRootWindows()[0]);
@@ -49,7 +75,9 @@ typedef test::AshTestBase DisplayControllerTest;
#endif
TEST_F(DisplayControllerTest, MAYBE_SecondaryDisplayLayout) {
+ TestObserver observer;
UpdateDisplay("500x500,400x400");
+ EXPECT_EQ(2, observer.CountAndReset()); // resize and add
gfx::Display* secondary_display =
aura::Env::GetInstance()->display_manager()->GetDisplayAt(1);
gfx::Insets insets(5, 5, 5, 5);
@@ -62,26 +90,32 @@ TEST_F(DisplayControllerTest, MAYBE_SecondaryDisplayLayout) {
// Layout the secondary display to the bottom of the primary.
SetSecondaryDisplayLayout(DisplayLayout::BOTTOM);
+ EXPECT_EQ(1, observer.CountAndReset());
EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
EXPECT_EQ("0,500 400x400", GetSecondaryDisplay().bounds().ToString());
EXPECT_EQ("5,505 390x390", GetSecondaryDisplay().work_area().ToString());
// Layout the secondary display to the left of the primary.
SetSecondaryDisplayLayout(DisplayLayout::LEFT);
+ EXPECT_EQ(1, observer.CountAndReset());
EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
EXPECT_EQ("-400,0 400x400", GetSecondaryDisplay().bounds().ToString());
EXPECT_EQ("-395,5 390x390", GetSecondaryDisplay().work_area().ToString());
// Layout the secondary display to the top of the primary.
SetSecondaryDisplayLayout(DisplayLayout::TOP);
+ EXPECT_EQ(1, observer.CountAndReset());
EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
EXPECT_EQ("0,-400 400x400", GetSecondaryDisplay().bounds().ToString());
EXPECT_EQ("5,-395 390x390", GetSecondaryDisplay().work_area().ToString());
}
TEST_F(DisplayControllerTest, MAYBE_BoundsUpdated) {
+ TestObserver observer;
SetSecondaryDisplayLayout(DisplayLayout::BOTTOM);
- UpdateDisplay("200x200,300x300");
+ UpdateDisplay("200x200,300x300"); // layout, resize and add.
+ EXPECT_EQ(3, observer.CountAndReset());
+
gfx::Display* secondary_display =
aura::Env::GetInstance()->display_manager()->GetDisplayAt(1);
gfx::Insets insets(5, 5, 5, 5);
@@ -92,20 +126,24 @@ TEST_F(DisplayControllerTest, MAYBE_BoundsUpdated) {
EXPECT_EQ("5,205 290x290", GetSecondaryDisplay().work_area().ToString());
UpdateDisplay("400x400,200x200");
+ EXPECT_EQ(2, observer.CountAndReset()); // two resizes
EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
EXPECT_EQ("0,400 200x200", GetSecondaryDisplay().bounds().ToString());
EXPECT_EQ("5,405 190x190", GetSecondaryDisplay().work_area().ToString());
UpdateDisplay("400x400,300x300");
+ EXPECT_EQ(1, observer.CountAndReset());
EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
EXPECT_EQ("0,400 300x300", GetSecondaryDisplay().bounds().ToString());
EXPECT_EQ("5,405 290x290", GetSecondaryDisplay().work_area().ToString());
UpdateDisplay("400x400");
+ EXPECT_EQ(1, observer.CountAndReset());
EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString());
EXPECT_EQ(1, gfx::Screen::GetNumDisplays());
UpdateDisplay("500x500,700x700");
+ EXPECT_EQ(2, observer.CountAndReset());
ASSERT_EQ(2, gfx::Screen::GetNumDisplays());
EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString());
EXPECT_EQ("0,500 700x700", GetSecondaryDisplay().bounds().ToString());
diff --git a/ash/display/multi_display_manager.cc b/ash/display/multi_display_manager.cc
index ca6d44d..9c3bce3 100644
--- a/ash/display/multi_display_manager.cc
+++ b/ash/display/multi_display_manager.cc
@@ -53,18 +53,13 @@ MultiDisplayManager::~MultiDisplayManager() {
}
// static
-void MultiDisplayManager::AddRemoveDisplay() {
- MultiDisplayManager* manager = static_cast<MultiDisplayManager*>(
- aura::Env::GetInstance()->display_manager());
- manager->AddRemoveDisplayImpl();
-}
-
void MultiDisplayManager::CycleDisplay() {
MultiDisplayManager* manager = static_cast<MultiDisplayManager*>(
aura::Env::GetInstance()->display_manager());
manager->CycleDisplayImpl();
}
+// static
void MultiDisplayManager::ToggleDisplayScale() {
MultiDisplayManager* manager = static_cast<MultiDisplayManager*>(
aura::Env::GetInstance()->display_manager());
@@ -223,8 +218,10 @@ void MultiDisplayManager::OnRootWindowResized(const aura::RootWindow* root,
const gfx::Size& old_size) {
if (!use_fullscreen_host_window()) {
gfx::Display& display = FindDisplayForRootWindow(root);
- display.SetSize(root->GetHostSize());
- NotifyBoundsChanged(display);
+ if (display.size() != root->GetHostSize()) {
+ display.SetSize(root->GetHostSize());
+ NotifyBoundsChanged(display);
+ }
}
}
@@ -242,7 +239,7 @@ void MultiDisplayManager::Init() {
AddDisplayFromSpec(std::string() /* default */);
}
-void MultiDisplayManager::AddRemoveDisplayImpl() {
+void MultiDisplayManager::CycleDisplayImpl() {
std::vector<gfx::Display> new_displays;
if (displays_.size() > 1) {
// Remove if there is more than one display.
@@ -252,25 +249,12 @@ void MultiDisplayManager::AddRemoveDisplayImpl() {
} else {
// Add if there is only one display.
new_displays.push_back(displays_[0]);
- new_displays.push_back(CreateDisplayFromSpec("50+50-1280x768"));
+ new_displays.push_back(CreateDisplayFromSpec("100+200-500x400"));
}
if (new_displays.size())
OnNativeDisplaysChanged(new_displays);
}
-void MultiDisplayManager::CycleDisplayImpl() {
- if (displays_.size() > 1) {
- std::vector<gfx::Display> new_displays;
- for (Displays::const_iterator iter = displays_.begin() + 1;
- iter != displays_.end(); ++iter) {
- gfx::Display display = *iter;
- new_displays.push_back(display);
- }
- new_displays.push_back(displays_.front());
- OnNativeDisplaysChanged(new_displays);
- }
-}
-
void MultiDisplayManager::ScaleDisplayImpl() {
if (displays_.size() > 0) {
std::vector<gfx::Display> new_displays;
@@ -290,6 +274,8 @@ void MultiDisplayManager::ScaleDisplayImpl() {
gfx::Display& MultiDisplayManager::FindDisplayForRootWindow(
const aura::RootWindow* root_window) {
int64 id = root_window->GetProperty(kDisplayIdKey);
+ // if id is |kInvaildDisplayID|, it's being deleted.
+ DCHECK(id != gfx::Display::kInvalidDisplayID);
for (Displays::iterator iter = displays_.begin();
iter != displays_.end(); ++iter) {
if ((*iter).id() == id)
diff --git a/ash/display/multi_display_manager.h b/ash/display/multi_display_manager.h
index 61e1163..85f2f2b 100644
--- a/ash/display/multi_display_manager.h
+++ b/ash/display/multi_display_manager.h
@@ -38,7 +38,6 @@ class ASH_EXPORT MultiDisplayManager : public aura::DisplayManager,
// Used to emulate display change when run in a desktop environment instead
// of on a device.
- static void AddRemoveDisplay();
static void CycleDisplay();
static void ToggleDisplayScale();
@@ -76,7 +75,6 @@ class ASH_EXPORT MultiDisplayManager : public aura::DisplayManager,
typedef std::vector<gfx::Display> Displays;
void Init();
- void AddRemoveDisplayImpl();
void CycleDisplayImpl();
void ScaleDisplayImpl();
gfx::Display& FindDisplayForRootWindow(const aura::RootWindow* root);
diff --git a/ash/display/multi_display_manager_unittest.cc b/ash/display/multi_display_manager_unittest.cc
index 401c526..83c5cab 100644
--- a/ash/display/multi_display_manager_unittest.cc
+++ b/ash/display/multi_display_manager_unittest.cc
@@ -195,29 +195,20 @@ TEST_F(MultiDisplayManagerTest, MAYBE_NativeDisplayTest) {
TEST_F(MultiDisplayManagerTest, MAYBE_EmulatorTest) {
EXPECT_EQ(1U, display_manager()->GetNumDisplays());
- internal::MultiDisplayManager::AddRemoveDisplay();
+ internal::MultiDisplayManager::CycleDisplay();
// Update primary and add seconary.
EXPECT_EQ(2U, display_manager()->GetNumDisplays());
- EXPECT_EQ("1 1 0", GetCountSummary());
+ EXPECT_EQ("0 1 0", GetCountSummary());
reset();
internal::MultiDisplayManager::CycleDisplay();
- EXPECT_EQ(2U, display_manager()->GetNumDisplays());
- // Observer gets called twice in this mode because
- // it gets notified both from |OnNativeDisplayChagned|
- // and from |RootWindowObserver|, which is the consequence of
- // |SetHostSize()|.
- EXPECT_EQ("4 0 0", GetCountSummary());
- reset();
-
- internal::MultiDisplayManager::AddRemoveDisplay();
EXPECT_EQ(1U, display_manager()->GetNumDisplays());
EXPECT_EQ("0 0 1", GetCountSummary());
reset();
internal::MultiDisplayManager::CycleDisplay();
- EXPECT_EQ(1U, display_manager()->GetNumDisplays());
- EXPECT_EQ("0 0 0", GetCountSummary());
+ EXPECT_EQ(2U, display_manager()->GetNumDisplays());
+ EXPECT_EQ("0 1 0", GetCountSummary());
reset();
}
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc
index 8155f35..7dec690 100644
--- a/ash/root_window_controller.cc
+++ b/ash/root_window_controller.cc
@@ -8,6 +8,7 @@
#include "ash/desktop_background/desktop_background_widget_controller.h"
#include "ash/display/display_controller.h"
+#include "ash/display/multi_display_manager.h"
#include "ash/shell.h"
#include "ash/shell_factory.h"
#include "ash/shell_window_ids.h"
@@ -293,6 +294,12 @@ RootWindowController::RootWindowController(aura::RootWindow* root_window)
}
RootWindowController::~RootWindowController() {
+ Shutdown();
+ root_window_.reset();
+}
+
+void RootWindowController::Shutdown() {
+ CloseChildWindows();
if (Shell::GetActiveRootWindow() == root_window_.get()) {
Shell::GetInstance()->set_active_root_window(
Shell::GetPrimaryRootWindow() == root_window_.get() ?
@@ -302,7 +309,11 @@ RootWindowController::~RootWindowController() {
event_client_.reset();
screen_dimmer_.reset();
workspace_controller_.reset();
- root_window_.reset();
+ // Forget with the display ID so that display lookup
+ // ends up with invalid display.
+ root_window_->ClearProperty(kDisplayIdKey);
+ // And this root window should no longer process events.
+ root_window_->PrepareForShutdown();
}
aura::Window* RootWindowController::GetContainer(int container_id) {
diff --git a/ash/root_window_controller.h b/ash/root_window_controller.h
index 473c96e..c17d85a 100644
--- a/ash/root_window_controller.h
+++ b/ash/root_window_controller.h
@@ -59,6 +59,12 @@ class RootWindowController {
void CreateContainers();
void InitLayoutManagers();
+ // Deletes associated objects and clears the state, but doesn't delete
+ // the root window yet. This is used to delete a secondary displays'
+ // root window safely when the display disconnect signal is received,
+ // which may come while we're in the nested message loop.
+ void Shutdown();
+
// Deletes all child windows and performs necessary cleanup.
void CloseChildWindows();
diff --git a/ash/ui_controls_ash.cc b/ash/ui_controls_ash.cc
index 7463a53..f2aba71 100644
--- a/ash/ui_controls_ash.cc
+++ b/ash/ui_controls_ash.cc
@@ -7,6 +7,7 @@
#include "ash/wm/coordinate_conversion.h"
#include "ash/wm/window_properties.h"
#include "ui/aura/client/capture_client.h"
+#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/root_window.h"
#include "ui/aura/ui_controls_aura.h"
#include "ui/gfx/screen.h"
@@ -32,18 +33,25 @@ ui_controls::UIControlsAura* GetUIControlsForRootWindow(
}
// Returns the UIControls object for the RootWindow at the |point| in
-// absolute screen coordinates. NULL if there is no RootWindow under the
-// |point|.
-ui_controls::UIControlsAura* GetUIControlsAt(const gfx::Point& point) {
+// virtual screen coordinates, and updates the |point| relative to the
+// UIControlsAura's root window. NULL if there is no RootWindow under
+// the |point|.
+ui_controls::UIControlsAura* GetUIControlsAt(gfx::Point* point) {
// If there is a capture events must be relative to it.
aura::client::CaptureClient* capture_client =
GetCaptureClient(ash::Shell::GetInstance()->GetPrimaryRootWindow());
- if (capture_client && capture_client->GetCaptureWindow()) {
- return GetUIControlsForRootWindow(
- capture_client->GetCaptureWindow()->GetRootWindow());
- }
- aura::RootWindow* root = wm::GetRootWindowAt(point);
- return root ? GetUIControlsForRootWindow(root) : NULL;
+ aura::RootWindow* root = NULL;
+ if (capture_client && capture_client->GetCaptureWindow())
+ root = capture_client->GetCaptureWindow()->GetRootWindow();
+ else
+ root = wm::GetRootWindowAt(*point);
+
+ aura::client::ScreenPositionClient* screen_position_client =
+ aura::client::GetScreenPositionClient(root);
+ if (screen_position_client)
+ screen_position_client->ConvertPointFromScreen(root, point);
+
+ return GetUIControlsForRootWindow(root);
}
} // namespace
@@ -82,25 +90,25 @@ class UIControlsAsh : public ui_controls::UIControlsAura {
}
virtual bool SendMouseMove(long x, long y) OVERRIDE {
- ui_controls::UIControlsAura* ui_controls =
- GetUIControlsAt(gfx::Point(x, y));
- return ui_controls && ui_controls->SendMouseMove(x, y);
+ gfx::Point p(x, y);
+ ui_controls::UIControlsAura* ui_controls = GetUIControlsAt(&p);
+ return ui_controls && ui_controls->SendMouseMove(p.x(), p.y());
}
virtual bool SendMouseMoveNotifyWhenDone(
long x,
long y,
const base::Closure& closure) OVERRIDE {
- ui_controls::UIControlsAura* ui_controls =
- GetUIControlsAt(gfx::Point(x, y));
+ gfx::Point p(x, y);
+ ui_controls::UIControlsAura* ui_controls = GetUIControlsAt(&p);
return ui_controls &&
- ui_controls->SendMouseMoveNotifyWhenDone(x, y, closure);
+ ui_controls->SendMouseMoveNotifyWhenDone(p.x(), p.y(), closure);
}
virtual bool SendMouseEvents(ui_controls::MouseButton type,
int state) OVERRIDE {
- ui_controls::UIControlsAura* ui_controls =
- GetUIControlsAt(gfx::Screen::GetCursorScreenPoint());
+ gfx::Point p(gfx::Screen::GetCursorScreenPoint());
+ ui_controls::UIControlsAura* ui_controls = GetUIControlsAt(&p);
return ui_controls && ui_controls->SendMouseEvents(type, state);
}
@@ -108,15 +116,15 @@ class UIControlsAsh : public ui_controls::UIControlsAura {
ui_controls::MouseButton type,
int state,
const base::Closure& closure) OVERRIDE {
- ui_controls::UIControlsAura* ui_controls =
- GetUIControlsAt(gfx::Screen::GetCursorScreenPoint());
+ gfx::Point p(gfx::Screen::GetCursorScreenPoint());
+ ui_controls::UIControlsAura* ui_controls = GetUIControlsAt(&p);
return ui_controls && ui_controls->SendMouseEventsNotifyWhenDone(
type, state, closure);
}
virtual bool SendMouseClick(ui_controls::MouseButton type) OVERRIDE {
- ui_controls::UIControlsAura* ui_controls =
- GetUIControlsAt(gfx::Screen::GetCursorScreenPoint());
+ gfx::Point p(gfx::Screen::GetCursorScreenPoint());
+ ui_controls::UIControlsAura* ui_controls = GetUIControlsAt(&p);
return ui_controls && ui_controls->SendMouseClick(type);
}
diff --git a/ash/wm/toplevel_window_event_filter.cc b/ash/wm/toplevel_window_event_filter.cc
index 5909203..a79f91f 100644
--- a/ash/wm/toplevel_window_event_filter.cc
+++ b/ash/wm/toplevel_window_event_filter.cc
@@ -96,12 +96,15 @@ void ToplevelWindowEventFilter::ScopedWindowResizer::OnWindowDestroying(
ToplevelWindowEventFilter::ToplevelWindowEventFilter(aura::Window* owner)
: in_move_loop_(false),
+ move_cancelled_(false),
in_gesture_resize_(false),
grid_size_(0) {
aura::client::SetWindowMoveClient(owner, this);
+ Shell::GetInstance()->display_controller()->AddObserver(this);
}
ToplevelWindowEventFilter::~ToplevelWindowEventFilter() {
+ Shell::GetInstance()->display_controller()->RemoveObserver(this);
}
bool ToplevelWindowEventFilter::PreHandleKeyEvent(aura::Window* target,
@@ -249,10 +252,12 @@ ui::EventResult ToplevelWindowEventFilter::PreHandleGestureEvent(
return ui::ER_CONSUMED;
}
-void ToplevelWindowEventFilter::RunMoveLoop(aura::Window* source,
- const gfx::Point& drag_offset) {
+aura::client::WindowMoveResult ToplevelWindowEventFilter::RunMoveLoop(
+ aura::Window* source,
+ const gfx::Point& drag_offset) {
DCHECK(!in_move_loop_); // Can only handle one nested loop at a time.
in_move_loop_ = true;
+ move_cancelled_ = false;
aura::RootWindow* root_window = source->GetRootWindow();
DCHECK(root_window);
gfx::Point drag_location;
@@ -276,6 +281,8 @@ void ToplevelWindowEventFilter::RunMoveLoop(aura::Window* source,
run_loop.Run();
#endif // !defined(OS_MACOSX)
in_gesture_resize_ = in_move_loop_ = false;
+ return move_cancelled_ ? aura::client::MOVE_CANCELED :
+ aura::client::MOVE_SUCCESSFUL;
}
void ToplevelWindowEventFilter::EndMoveLoop() {
@@ -290,6 +297,16 @@ void ToplevelWindowEventFilter::EndMoveLoop() {
quit_closure_.Run();
}
+void ToplevelWindowEventFilter::OnDisplayConfigurationChanging() {
+ if (in_move_loop_) {
+ move_cancelled_ = true;
+ EndMoveLoop();
+ } else if (window_resizer_.get()) {
+ window_resizer_->resizer()->RevertDrag();
+ window_resizer_.reset();
+ }
+}
+
// static
WindowResizer* ToplevelWindowEventFilter::CreateWindowResizer(
aura::Window* window,
diff --git a/ash/wm/toplevel_window_event_filter.h b/ash/wm/toplevel_window_event_filter.h
index 5b5710c..4be6c6c 100644
--- a/ash/wm/toplevel_window_event_filter.h
+++ b/ash/wm/toplevel_window_event_filter.h
@@ -8,6 +8,7 @@
#include <set>
#include "ash/ash_export.h"
+#include "ash/display/display_controller.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
@@ -30,7 +31,8 @@ class WindowResizer;
class ASH_EXPORT ToplevelWindowEventFilter
: public aura::EventFilter,
- public aura::client::WindowMoveClient {
+ public aura::client::WindowMoveClient,
+ public DisplayController::Observer {
public:
explicit ToplevelWindowEventFilter(aura::Window* owner);
virtual ~ToplevelWindowEventFilter();
@@ -54,10 +56,14 @@ class ASH_EXPORT ToplevelWindowEventFilter
ui::GestureEvent* event) OVERRIDE;
// Overridden form aura::client::WindowMoveClient:
- virtual void RunMoveLoop(aura::Window* source,
- const gfx::Point& drag_offset) OVERRIDE;
+ virtual aura::client::WindowMoveResult RunMoveLoop(
+ aura::Window* source,
+ const gfx::Point& drag_offset) OVERRIDE;
virtual void EndMoveLoop() OVERRIDE;
+ // Overridden form ash::DisplayController::Observer:
+ virtual void OnDisplayConfigurationChanging() OVERRIDE;
+
protected:
// Creates a new WindowResizer.
virtual WindowResizer* CreateWindowResizer(aura::Window* window,
@@ -97,6 +103,10 @@ class ASH_EXPORT ToplevelWindowEventFilter
// Are we running a nested message loop from RunMoveLoop().
bool in_move_loop_;
+ // Was the move operation cancelled? Used only when the nested loop
+ // is used to move a window.
+ bool move_cancelled_;
+
// Is a gesture-resize in progress?
bool in_gesture_resize_;
diff --git a/ash/wm/toplevel_window_event_filter_unittest.cc b/ash/wm/toplevel_window_event_filter_unittest.cc
index 0974b63..d3a287a 100644
--- a/ash/wm/toplevel_window_event_filter_unittest.cc
+++ b/ash/wm/toplevel_window_event_filter_unittest.cc
@@ -422,7 +422,7 @@ TEST_F(ToplevelWindowEventFilterTest, DragSnaps) {
aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
target.get());
generator.PressLeftButton();
- generator.MoveMouseTo(generator.current_location().Add(gfx::Point(11, 21)));
+ generator.MoveMouseBy(11, 21);
// Execute any scheduled draws so that pending mouse events are processed.
RunAllPendingInMessageLoop();
@@ -519,7 +519,7 @@ TEST_F(ToplevelWindowEventFilterTest, MAYBE_EscapeReverts) {
aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
target.get());
generator.PressLeftButton();
- generator.MoveMouseTo(generator.current_location().Add(gfx::Point(10, 11)));
+ generator.MoveMouseBy(10, 11);
// Execute any scheduled draws so that pending mouse events are processed.
RunAllPendingInMessageLoop();
diff --git a/ash/wm/workspace/workspace_window_resizer_unittest.cc b/ash/wm/workspace/workspace_window_resizer_unittest.cc
index 4188880..4eea3da 100644
--- a/ash/wm/workspace/workspace_window_resizer_unittest.cc
+++ b/ash/wm/workspace/workspace_window_resizer_unittest.cc
@@ -141,15 +141,15 @@ class WorkspaceWindowResizerTest : public test::AshTestBase {
// Fails on win_aura since wm::GetRootWindowRelativeToWindow is not implemented
// yet for the platform.
#if defined(OS_WIN)
-#define MAYBE_WindowDragWithMultiMonitors \
- DISABLED_WindowDragWithMultiMonitors
-#define MAYBE_WindowDragWithMultiMonitorsRightToLeft \
- DISABLED_WindowDragWithMultiMonitorsRightToLeft
+#define MAYBE_WindowDragWithMultiDisplays \
+ DISABLED_WindowDragWithMultiDisplays
+#define MAYBE_WindowDragWithMultiDisplaysRightToLeft \
+ DISABLED_WindowDragWithMultiDisplaysRightToLeft
#define MAYBE_PhantomStyle DISABLED_PhantomStyle
#else
-#define MAYBE_WindowDragWithMultiMonitors WindowDragWithMultiMonitors
-#define MAYBE_WindowDragWithMultiMonitorsRightToLeft \
- WindowDragWithMultiMonitorsRightToLeft
+#define MAYBE_WindowDragWithMultiDisplays WindowDragWithMultiDisplays
+#define MAYBE_WindowDragWithMultiDisplaysRightToLeft \
+ WindowDragWithMultiDisplaysRightToLeft
#define MAYBE_PhantomStyle PhantomStyle
#endif
@@ -487,7 +487,7 @@ TEST_F(WorkspaceWindowResizerTest, Edge) {
}
// Verifies a window can be moved from the primary display to another.
-TEST_F(WorkspaceWindowResizerTest, MAYBE_WindowDragWithMultiMonitors) {
+TEST_F(WorkspaceWindowResizerTest, MAYBE_WindowDragWithMultiDisplays) {
// The secondary display is logically on the right, but on the system (e.g. X)
// layer, it's below the primary one. See UpdateDisplay() in ash_test_base.cc.
UpdateDisplay("800x600,800x600");
@@ -554,7 +554,7 @@ TEST_F(WorkspaceWindowResizerTest, MAYBE_WindowDragWithMultiMonitors) {
// Verifies a window can be moved from the secondary display to primary.
TEST_F(WorkspaceWindowResizerTest,
- MAYBE_WindowDragWithMultiMonitorsRightToLeft) {
+ MAYBE_WindowDragWithMultiDisplaysRightToLeft) {
UpdateDisplay("800x600,800x600");
Shell::GetInstance()->shelf()->LayoutShelf();
Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index ddd6543..965103d 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -33,6 +33,7 @@
#if defined(USE_ASH)
#include "ash/display/display_controller.h"
+#include "ash/display/multi_display_manager.h"
#include "ash/shell.h"
#include "ui/aura/test/event_generator.h"
#include "ui/aura/root_window.h"
@@ -940,8 +941,7 @@ IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest,
ResetIDs(browser2->tab_strip_model(), 100);
// Move the second browser to the second display.
- std::vector<aura::RootWindow*> roots(
- ash::Shell::GetInstance()->display_controller()->GetAllRootWindows());
+ std::vector<aura::RootWindow*> roots(ash::Shell::GetAllRootWindows());
ASSERT_EQ(2u, roots.size());
aura::RootWindow* second_root = roots[1];
gfx::Rect work_area = gfx::Screen::GetDisplayNearestWindow(
@@ -974,6 +974,153 @@ IN_PROC_BROWSER_TEST_P(DetachToBrowserInSeparateDisplayTabDragControllerTest,
EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
}
+namespace {
+
+class DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest
+ : public TabDragControllerTest {
+ public:
+ DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest() {}
+
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ TabDragControllerTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitchASCII("aura-host-window-size",
+ "0+0-250x250,251+0-250x250");
+ }
+
+ bool Press(const gfx::Point& position) {
+ return ui_test_utils::SendMouseMoveSync(position) &&
+ ui_test_utils::SendMouseEventsSync(ui_controls::LEFT,
+ ui_controls::DOWN);
+ }
+
+ bool DragTabAndExecuteTaskWhenDone(const gfx::Point& position,
+ const base::Closure& task) {
+ return ui_controls::SendMouseMoveNotifyWhenDone(
+ position.x(), position.y(), task);
+ }
+
+ void QuitWhenNotDragging() {
+ test::QuitWhenNotDraggingImpl();
+ MessageLoop::current()->Run();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(
+ DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest);
+};
+
+// Invoked from the nested message loop.
+void CancelDragTabToWindowInSeparateDisplayStep3(
+ TabStrip* tab_strip) {
+ ASSERT_FALSE(tab_strip->IsDragSessionActive());
+ ASSERT_TRUE(TabDragController::IsActive());
+ ASSERT_EQ(2u, BrowserList::size());
+
+ // Switching display mode should cancel the drag operation.
+ ash::internal::MultiDisplayManager::CycleDisplay();
+}
+
+// Invoked from the nested message loop.
+void CancelDragTabToWindowInSeparateDisplayStep2(
+ DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest* test,
+ TabStrip* tab_strip,
+ aura::RootWindow* current_root,
+ gfx::Point final_destination) {
+ ASSERT_FALSE(tab_strip->IsDragSessionActive());
+ ASSERT_TRUE(TabDragController::IsActive());
+ ASSERT_EQ(2u, BrowserList::size());
+
+ Browser* new_browser = *(++BrowserList::begin());
+ EXPECT_EQ(current_root,
+ new_browser->window()->GetNativeWindow()->GetRootWindow());
+
+ ASSERT_TRUE(test->DragTabAndExecuteTaskWhenDone(
+ final_destination,
+ base::Bind(&CancelDragTabToWindowInSeparateDisplayStep3,
+ tab_strip)));
+}
+
+} // namespace
+
+// Drags from browser to a second display and releases input.
+IN_PROC_BROWSER_TEST_F(
+ DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest,
+ CancelDragTabToWindowIn2ndDisplay) {
+ // Add another tab.
+ AddTabAndResetBrowser(browser());
+ TabStrip* tab_strip = GetTabStripForBrowser(browser());
+
+ EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
+
+ // Move the second browser to the second display.
+ std::vector<aura::RootWindow*> roots(ash::Shell::GetAllRootWindows());
+ ASSERT_EQ(2u, roots.size());
+ gfx::Point final_destination =
+ gfx::Screen::GetDisplayNearestWindow(roots[1]).work_area().CenterPoint();
+
+ // Move to the first tab and drag it enough so that it detaches, but not
+ // enough to move to another display.
+ gfx::Point tab_0_dst(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
+ ASSERT_TRUE(Press(tab_0_dst));
+ tab_0_dst.Offset(0, GetDetachY(tab_strip));
+ ASSERT_TRUE(DragTabAndExecuteTaskWhenDone(
+ tab_0_dst, base::Bind(&CancelDragTabToWindowInSeparateDisplayStep2,
+ this, tab_strip, roots[0], final_destination)));
+ QuitWhenNotDragging();
+
+ ASSERT_EQ(1u, BrowserList::size());
+ ASSERT_FALSE(tab_strip->IsDragSessionActive());
+ ASSERT_FALSE(TabDragController::IsActive());
+ EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
+
+ // Release the mouse
+ ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(
+ ui_controls::LEFT, ui_controls::UP));
+}
+
+// Drags from browser from a second display to primary and releases input.
+IN_PROC_BROWSER_TEST_F(
+ DetachToBrowserInSeparateDisplayAndCancelTabDragControllerTest,
+ CancelDragTabToWindowIn1stDisplay) {
+ std::vector<aura::RootWindow*> roots(ash::Shell::GetAllRootWindows());
+ ASSERT_EQ(2u, roots.size());
+
+ // Add another tab.
+ AddTabAndResetBrowser(browser());
+ TabStrip* tab_strip = GetTabStripForBrowser(browser());
+
+ EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
+ EXPECT_EQ(roots[0], browser()->window()->GetNativeWindow()->GetRootWindow());
+
+ gfx::Rect work_area =
+ gfx::Screen::GetDisplayNearestWindow(roots[1]).work_area();
+ browser()->window()->SetBounds(work_area);
+ EXPECT_EQ(roots[1], browser()->window()->GetNativeWindow()->GetRootWindow());
+
+ // Move the second browser to the display.
+ gfx::Point final_destination =
+ gfx::Screen::GetDisplayNearestWindow(roots[0]).work_area().CenterPoint();
+
+ // Move to the first tab and drag it enough so that it detaches, but not
+ // enough to move to another display.
+ gfx::Point tab_0_dst(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
+ ASSERT_TRUE(Press(tab_0_dst));
+ tab_0_dst.Offset(0, GetDetachY(tab_strip));
+ ASSERT_TRUE(DragTabAndExecuteTaskWhenDone(
+ tab_0_dst, base::Bind(&CancelDragTabToWindowInSeparateDisplayStep2,
+ this, tab_strip, roots[1], final_destination)));
+ QuitWhenNotDragging();
+
+ ASSERT_EQ(1u, BrowserList::size());
+ ASSERT_FALSE(tab_strip->IsDragSessionActive());
+ ASSERT_FALSE(TabDragController::IsActive());
+ EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
+
+ // Release the mouse
+ ASSERT_TRUE(ui_test_utils::SendMouseEventsSync(
+ ui_controls::LEFT, ui_controls::UP));
+}
+
#endif
#if defined(USE_ASH)
diff --git a/ui/aura/client/window_move_client.h b/ui/aura/client/window_move_client.h
index 048e572..2d2a8cb 100644
--- a/ui/aura/client/window_move_client.h
+++ b/ui/aura/client/window_move_client.h
@@ -15,13 +15,21 @@ namespace aura {
class Window;
namespace client {
+enum WindowMoveResult {
+ MOVE_SUCCESSFUL, // Moving window was successful.
+ MOVE_CANCELED // Moving window was canceled.
+};
+
// An interface implemented by an object that manages programatically keyed
// window moving.
class AURA_EXPORT WindowMoveClient {
public:
// Starts a nested message loop for moving the window. |drag_offset| is the
// offset from the window origin to the cursor when the drag was started.
- virtual void RunMoveLoop(Window* window, const gfx::Point& drag_offset) = 0;
+ // Returns MOVE_SUCCESSFUL if the move has completed successfully, or
+ // MOVE_CANCELED otherwise.
+ virtual WindowMoveResult RunMoveLoop(Window* window,
+ const gfx::Point& drag_offset) = 0;
// Ends a previously started move loop.
virtual void EndMoveLoop() = 0;
diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc
index 3d0981f..7662cfe 100644
--- a/ui/aura/root_window.cc
+++ b/ui/aura/root_window.cc
@@ -201,6 +201,12 @@ void RootWindow::HideRootWindow() {
host_->Hide();
}
+void RootWindow::PrepareForShutdown() {
+ host_->PrepareForShutdown();
+ // discard synthesize event request as well.
+ synthesize_mouse_move_ = false;
+}
+
RootWindowHostDelegate* RootWindow::AsRootWindowHostDelegate() {
return this;
}
diff --git a/ui/aura/root_window.h b/ui/aura/root_window.h
index 7cd317b..cdc05c0 100644
--- a/ui/aura/root_window.h
+++ b/ui/aura/root_window.h
@@ -126,6 +126,9 @@ class AURA_EXPORT RootWindow : public ui::CompositorDelegate,
// Hides the root window host.
void HideRootWindow();
+ // Stop listening events in preparation for shutdown.
+ void PrepareForShutdown();
+
RootWindowHostDelegate* AsRootWindowHostDelegate();
// Sets the size of the root window.
diff --git a/ui/aura/root_window_host.h b/ui/aura/root_window_host.h
index 74502bf..ee5eb20 100644
--- a/ui/aura/root_window_host.h
+++ b/ui/aura/root_window_host.h
@@ -105,6 +105,9 @@ class RootWindowHost {
// Called when the device scale factor of the root window has chagned.
virtual void OnDeviceScaleFactorChanged(float device_scale_factor) = 0;
+
+ // Stop listening events in preparation for shutdown.
+ virtual void PrepareForShutdown() = 0;
};
} // namespace aura
diff --git a/ui/aura/root_window_host_linux.cc b/ui/aura/root_window_host_linux.cc
index 9b98856..4e5af61 100644
--- a/ui/aura/root_window_host_linux.cc
+++ b/ui/aura/root_window_host_linux.cc
@@ -1097,6 +1097,10 @@ void RootWindowHostLinux::OnDeviceScaleFactorChanged(
image_cursors_->Reload(device_scale_factor);
}
+void RootWindowHostLinux::PrepareForShutdown() {
+ base::MessagePumpAuraX11::Current()->RemoveDispatcherForWindow(xwindow_);
+}
+
bool RootWindowHostLinux::IsWindowManagerPresent() {
// Per ICCCM 2.8, "Manager Selections", window managers should take ownership
// of WM_Sn selections (where n is a screen number).
diff --git a/ui/aura/root_window_host_linux.h b/ui/aura/root_window_host_linux.h
index 8e91c4d..6338dd8 100644
--- a/ui/aura/root_window_host_linux.h
+++ b/ui/aura/root_window_host_linux.h
@@ -56,6 +56,7 @@ class RootWindowHostLinux : public RootWindowHost,
std::vector<unsigned char>* png_representation) OVERRIDE;
virtual void PostNativeEvent(const base::NativeEvent& event) OVERRIDE;
virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
+ virtual void PrepareForShutdown() OVERRIDE;
// Returns true if there's an X window manager present... in most cases. Some
// window managers (notably, ion3) don't implement enough of ICCCM for us to
diff --git a/ui/aura/root_window_host_win.cc b/ui/aura/root_window_host_win.cc
index aa36202..a4b2e2d 100644
--- a/ui/aura/root_window_host_win.cc
+++ b/ui/aura/root_window_host_win.cc
@@ -304,6 +304,10 @@ void RootWindowHostWin::OnDeviceScaleFactorChanged(
NOTIMPLEMENTED();
}
+void RootWindowHostWin::PrepareForShutdown() {
+ NOTIMPLEMENTED();
+}
+
void RootWindowHostWin::OnClose() {
// TODO: this obviously shouldn't be here.
MessageLoopForUI::current()->Quit();
diff --git a/ui/aura/root_window_host_win.h b/ui/aura/root_window_host_win.h
index fdc5d9b..8c8810c 100644
--- a/ui/aura/root_window_host_win.h
+++ b/ui/aura/root_window_host_win.h
@@ -44,6 +44,7 @@ class RootWindowHostWin : public RootWindowHost, public ui::WindowImpl {
std::vector<unsigned char>* png_representation) OVERRIDE;
virtual void PostNativeEvent(const base::NativeEvent& native_event) OVERRIDE;
virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
+ virtual void PrepareForShutdown() OVERRIDE;
private:
BEGIN_MSG_MAP_EX(RootWindowHostWin)
diff --git a/ui/views/widget/desktop_root_window_host_win.cc b/ui/views/widget/desktop_root_window_host_win.cc
index f85cdb2d..b68b3a3 100644
--- a/ui/views/widget/desktop_root_window_host_win.cc
+++ b/ui/views/widget/desktop_root_window_host_win.cc
@@ -121,6 +121,9 @@ void DesktopRootWindowHostWin::OnDeviceScaleFactorChanged(
float device_scale_factor) {
}
+void DesktopRootWindowHostWin::PrepareForShutdown() {
+}
+
////////////////////////////////////////////////////////////////////////////////
// DesktopRootWindowHostWin, HWNDMessageHandlerDelegate implementation:
diff --git a/ui/views/widget/desktop_root_window_host_win.h b/ui/views/widget/desktop_root_window_host_win.h
index 5edf687..9293aea 100644
--- a/ui/views/widget/desktop_root_window_host_win.h
+++ b/ui/views/widget/desktop_root_window_host_win.h
@@ -50,6 +50,7 @@ class DesktopRootWindowHostWin : public DesktopRootWindowHost,
std::vector<unsigned char>* png_representation) OVERRIDE;
virtual void PostNativeEvent(const base::NativeEvent& native_event) OVERRIDE;
virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
+ virtual void PrepareForShutdown() OVERRIDE;
// Overridden from HWNDMessageHandlerDelegate:
virtual bool IsWidgetWindow() const OVERRIDE;
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index 2deab23..a90db1f 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -676,9 +676,10 @@ Widget::MoveLoopResult NativeWidgetAura::RunMoveLoop(
if (window_->parent() &&
aura::client::GetWindowMoveClient(window_->parent())) {
SetCapture();
- aura::client::GetWindowMoveClient(window_->parent())->RunMoveLoop(
- window_, drag_offset);
- return Widget::MOVE_LOOP_SUCCESSFUL;
+ if (aura::client::GetWindowMoveClient(window_->parent())->RunMoveLoop(
+ window_, drag_offset) == aura::client::MOVE_SUCCESSFUL) {
+ return Widget::MOVE_LOOP_SUCCESSFUL;
+ }
}
return Widget::MOVE_LOOP_CANCELED;
}
diff --git a/ui/views/widget/x11_desktop_window_move_client.cc b/ui/views/widget/x11_desktop_window_move_client.cc
index 329a656..adb6ff3 100644
--- a/ui/views/widget/x11_desktop_window_move_client.cc
+++ b/ui/views/widget/x11_desktop_window_move_client.cc
@@ -69,8 +69,9 @@ ui::EventResult X11DesktopWindowMoveClient::PreHandleGestureEvent(
return ui::ER_UNHANDLED;
}
-void X11DesktopWindowMoveClient::RunMoveLoop(aura::Window* source,
- const gfx::Point& drag_offset) {
+aura::client::WindowMoveResult X11DesktopWindowMoveClient::RunMoveLoop(
+ aura::Window* source,
+ const gfx::Point& drag_offset) {
DCHECK(!in_move_loop_); // Can only handle one nested loop at a time.
in_move_loop_ = true;
window_offset_ = drag_offset;
@@ -94,7 +95,7 @@ void X11DesktopWindowMoveClient::RunMoveLoop(aura::Window* source,
XUngrabServer(display);
if (ret != GrabSuccess) {
DLOG(ERROR) << "Grabbing new tab for dragging failed: " << ret;
- return;
+ return aura::client::MOVE_CANCELED;
}
MessageLoopForUI* loop = MessageLoopForUI::current();
@@ -102,6 +103,7 @@ void X11DesktopWindowMoveClient::RunMoveLoop(aura::Window* source,
base::RunLoop run_loop(aura::Env::GetInstance()->GetDispatcher());
quit_closure_ = run_loop.QuitClosure();
run_loop.Run();
+ return aura::client::MOVE_SUCCESSFUL;
}
void X11DesktopWindowMoveClient::EndMoveLoop() {
diff --git a/ui/views/widget/x11_desktop_window_move_client.h b/ui/views/widget/x11_desktop_window_move_client.h
index 114e5b7..f80bce6 100644
--- a/ui/views/widget/x11_desktop_window_move_client.h
+++ b/ui/views/widget/x11_desktop_window_move_client.h
@@ -34,8 +34,9 @@ class VIEWS_EXPORT X11DesktopWindowMoveClient
ui::GestureEvent* event) OVERRIDE;
// Overridden from aura::client::WindowMoveClient:
- virtual void RunMoveLoop(aura::Window* window,
- const gfx::Point& drag_offset) OVERRIDE;
+ virtual aura::client::WindowMoveResult RunMoveLoop(
+ aura::Window* window,
+ const gfx::Point& drag_offset) OVERRIDE;
virtual void EndMoveLoop() OVERRIDE;
private: