diff options
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: |