Index: ash/common/wm/workspace/multi_window_resize_controller.cc |
diff --git a/ash/common/wm/workspace/multi_window_resize_controller.cc b/ash/common/wm/workspace/multi_window_resize_controller.cc |
deleted file mode 100644 |
index 48879e835dc3edef6c33dd73499fd8aeaf31ae1f..0000000000000000000000000000000000000000 |
--- a/ash/common/wm/workspace/multi_window_resize_controller.cc |
+++ /dev/null |
@@ -1,540 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "ash/common/wm/workspace/multi_window_resize_controller.h" |
- |
-#include "ash/common/wm/workspace/workspace_window_resizer.h" |
-#include "ash/common/wm_window.h" |
-#include "ash/public/cpp/shell_window_ids.h" |
-#include "ash/resources/grit/ash_resources.h" |
-#include "ash/root_window_controller.h" |
-#include "ui/base/cursor/cursor.h" |
-#include "ui/base/hit_test.h" |
-#include "ui/base/resource/resource_bundle.h" |
-#include "ui/display/screen.h" |
-#include "ui/gfx/canvas.h" |
-#include "ui/gfx/image/image.h" |
-#include "ui/views/view.h" |
-#include "ui/views/widget/widget.h" |
-#include "ui/views/widget/widget_delegate.h" |
-#include "ui/wm/core/compound_event_filter.h" |
- |
-namespace ash { |
-namespace { |
- |
-// Delay before showing. |
-const int kShowDelayMS = 400; |
- |
-// Delay before hiding. |
-const int kHideDelayMS = 500; |
- |
-// Padding from the bottom/right edge the resize widget is shown at. |
-const int kResizeWidgetPadding = 15; |
- |
-bool ContainsX(WmWindow* window, int x) { |
- return x >= 0 && x <= window->GetBounds().width(); |
-} |
- |
-bool ContainsScreenX(WmWindow* window, int x_in_screen) { |
- gfx::Point window_loc = |
- window->ConvertPointFromScreen(gfx::Point(x_in_screen, 0)); |
- return ContainsX(window, window_loc.x()); |
-} |
- |
-bool ContainsY(WmWindow* window, int y) { |
- return y >= 0 && y <= window->GetBounds().height(); |
-} |
- |
-bool ContainsScreenY(WmWindow* window, int y_in_screen) { |
- gfx::Point window_loc = |
- window->ConvertPointFromScreen(gfx::Point(0, y_in_screen)); |
- return ContainsY(window, window_loc.y()); |
-} |
- |
-bool Intersects(int x1, int max_1, int x2, int max_2) { |
- return x2 <= max_1 && max_2 > x1; |
-} |
- |
-} // namespace |
- |
-// View contained in the widget. Passes along mouse events to the |
-// MultiWindowResizeController so that it can start/stop the resize loop. |
-class MultiWindowResizeController::ResizeView : public views::View { |
- public: |
- explicit ResizeView(MultiWindowResizeController* controller, |
- Direction direction) |
- : controller_(controller), direction_(direction), image_(NULL) { |
- ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
- int image_id = direction == TOP_BOTTOM ? IDR_AURA_MULTI_WINDOW_RESIZE_H |
- : IDR_AURA_MULTI_WINDOW_RESIZE_V; |
- image_ = rb.GetImageNamed(image_id).ToImageSkia(); |
- } |
- |
- // views::View overrides: |
- gfx::Size GetPreferredSize() const override { |
- return gfx::Size(image_->width(), image_->height()); |
- } |
- void OnPaint(gfx::Canvas* canvas) override { |
- canvas->DrawImageInt(*image_, 0, 0); |
- } |
- bool OnMousePressed(const ui::MouseEvent& event) override { |
- gfx::Point location(event.location()); |
- views::View::ConvertPointToScreen(this, &location); |
- controller_->StartResize(location); |
- return true; |
- } |
- bool OnMouseDragged(const ui::MouseEvent& event) override { |
- gfx::Point location(event.location()); |
- views::View::ConvertPointToScreen(this, &location); |
- controller_->Resize(location, event.flags()); |
- return true; |
- } |
- void OnMouseReleased(const ui::MouseEvent& event) override { |
- controller_->CompleteResize(); |
- } |
- void OnMouseCaptureLost() override { controller_->CancelResize(); } |
- gfx::NativeCursor GetCursor(const ui::MouseEvent& event) override { |
- int component = (direction_ == LEFT_RIGHT) ? HTRIGHT : HTBOTTOM; |
- return ::wm::CompoundEventFilter::CursorForWindowComponent(component); |
- } |
- |
- private: |
- MultiWindowResizeController* controller_; |
- const Direction direction_; |
- const gfx::ImageSkia* image_; |
- |
- DISALLOW_COPY_AND_ASSIGN(ResizeView); |
-}; |
- |
-// MouseWatcherHost implementation for MultiWindowResizeController. Forwards |
-// Contains() to MultiWindowResizeController. |
-class MultiWindowResizeController::ResizeMouseWatcherHost |
- : public views::MouseWatcherHost { |
- public: |
- ResizeMouseWatcherHost(MultiWindowResizeController* host) : host_(host) {} |
- |
- // MouseWatcherHost overrides: |
- bool Contains(const gfx::Point& point_in_screen, |
- MouseEventType type) override { |
- return (type == MOUSE_PRESS) ? host_->IsOverResizeWidget(point_in_screen) |
- : host_->IsOverWindows(point_in_screen); |
- } |
- |
- private: |
- MultiWindowResizeController* host_; |
- |
- DISALLOW_COPY_AND_ASSIGN(ResizeMouseWatcherHost); |
-}; |
- |
-MultiWindowResizeController::ResizeWindows::ResizeWindows() |
- : window1(nullptr), window2(nullptr), direction(TOP_BOTTOM) {} |
- |
-MultiWindowResizeController::ResizeWindows::ResizeWindows( |
- const ResizeWindows& other) = default; |
- |
-MultiWindowResizeController::ResizeWindows::~ResizeWindows() {} |
- |
-bool MultiWindowResizeController::ResizeWindows::Equals( |
- const ResizeWindows& other) const { |
- return window1 == other.window1 && window2 == other.window2 && |
- direction == other.direction; |
-} |
- |
-MultiWindowResizeController::MultiWindowResizeController() {} |
- |
-MultiWindowResizeController::~MultiWindowResizeController() { |
- window_resizer_.reset(); |
- Hide(); |
-} |
- |
-void MultiWindowResizeController::Show(WmWindow* window, |
- int component, |
- const gfx::Point& point_in_window) { |
- // When the resize widget is showing we ignore Show() requests. Instead we |
- // only care about mouse movements from MouseWatcher. This is necessary as |
- // WorkspaceEventHandler only sees mouse movements over the windows, not all |
- // windows or over the desktop. |
- if (resize_widget_) |
- return; |
- |
- ResizeWindows windows(DetermineWindows(window, component, point_in_window)); |
- if (IsShowing() && windows_.Equals(windows)) |
- return; |
- |
- Hide(); |
- if (!windows.is_valid()) { |
- windows_ = ResizeWindows(); |
- return; |
- } |
- |
- windows_ = windows; |
- windows_.window1->aura_window()->AddObserver(this); |
- windows_.window2->aura_window()->AddObserver(this); |
- show_location_in_parent_ = |
- window->ConvertPointToTarget(window->GetParent(), point_in_window); |
- show_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kShowDelayMS), |
- this, |
- &MultiWindowResizeController::ShowIfValidMouseLocation); |
-} |
- |
-void MultiWindowResizeController::Hide() { |
- if (window_resizer_) |
- return; // Ignore hides while actively resizing. |
- |
- if (windows_.window1) { |
- windows_.window1->aura_window()->RemoveObserver(this); |
- windows_.window1 = NULL; |
- } |
- if (windows_.window2) { |
- windows_.window2->aura_window()->RemoveObserver(this); |
- windows_.window2 = NULL; |
- } |
- |
- show_timer_.Stop(); |
- |
- if (!resize_widget_) |
- return; |
- |
- for (size_t i = 0; i < windows_.other_windows.size(); ++i) |
- windows_.other_windows[i]->aura_window()->RemoveObserver(this); |
- mouse_watcher_.reset(); |
- resize_widget_.reset(); |
- windows_ = ResizeWindows(); |
-} |
- |
-void MultiWindowResizeController::MouseMovedOutOfHost() { |
- Hide(); |
-} |
- |
-void MultiWindowResizeController::OnWindowDestroying(aura::Window* window) { |
- // Have to explicitly reset the WindowResizer, otherwise Hide() does nothing. |
- window_resizer_.reset(); |
- Hide(); |
-} |
- |
-MultiWindowResizeController::ResizeWindows |
-MultiWindowResizeController::DetermineWindowsFromScreenPoint( |
- WmWindow* window) const { |
- gfx::Point mouse_location( |
- display::Screen::GetScreen()->GetCursorScreenPoint()); |
- mouse_location = window->ConvertPointFromScreen(mouse_location); |
- const int component = window->GetNonClientComponent(mouse_location); |
- return DetermineWindows(window, component, mouse_location); |
-} |
- |
-void MultiWindowResizeController::CreateMouseWatcher() { |
- mouse_watcher_.reset( |
- new views::MouseWatcher(new ResizeMouseWatcherHost(this), this)); |
- mouse_watcher_->set_notify_on_exit_time( |
- base::TimeDelta::FromMilliseconds(kHideDelayMS)); |
- mouse_watcher_->Start(); |
-} |
- |
-MultiWindowResizeController::ResizeWindows |
-MultiWindowResizeController::DetermineWindows(WmWindow* window, |
- int window_component, |
- const gfx::Point& point) const { |
- ResizeWindows result; |
- gfx::Point point_in_parent = |
- window->ConvertPointToTarget(window->GetParent(), point); |
- switch (window_component) { |
- case HTRIGHT: |
- result.direction = LEFT_RIGHT; |
- result.window1 = window; |
- result.window2 = FindWindowByEdge( |
- window, HTLEFT, window->GetBounds().right(), point_in_parent.y()); |
- break; |
- case HTLEFT: |
- result.direction = LEFT_RIGHT; |
- result.window1 = FindWindowByEdge( |
- window, HTRIGHT, window->GetBounds().x(), point_in_parent.y()); |
- result.window2 = window; |
- break; |
- case HTTOP: |
- result.direction = TOP_BOTTOM; |
- result.window1 = FindWindowByEdge(window, HTBOTTOM, point_in_parent.x(), |
- window->GetBounds().y()); |
- result.window2 = window; |
- break; |
- case HTBOTTOM: |
- result.direction = TOP_BOTTOM; |
- result.window1 = window; |
- result.window2 = FindWindowByEdge(window, HTTOP, point_in_parent.x(), |
- window->GetBounds().bottom()); |
- break; |
- default: |
- break; |
- } |
- return result; |
-} |
- |
-WmWindow* MultiWindowResizeController::FindWindowByEdge( |
- WmWindow* window_to_ignore, |
- int edge_want, |
- int x_in_parent, |
- int y_in_parent) const { |
- WmWindow* parent = window_to_ignore->GetParent(); |
- std::vector<WmWindow*> windows = parent->GetChildren(); |
- for (auto i = windows.rbegin(); i != windows.rend(); ++i) { |
- WmWindow* window = *i; |
- if (window == window_to_ignore || !window->IsVisible()) |
- continue; |
- |
- // Ignore windows without a non-client area. |
- if (!window->HasNonClientArea()) |
- continue; |
- |
- gfx::Point p = parent->ConvertPointToTarget( |
- window, gfx::Point(x_in_parent, y_in_parent)); |
- switch (edge_want) { |
- case HTLEFT: |
- if (ContainsY(window, p.y()) && p.x() == 0) |
- return window; |
- break; |
- case HTRIGHT: |
- if (ContainsY(window, p.y()) && p.x() == window->GetBounds().width()) |
- return window; |
- break; |
- case HTTOP: |
- if (ContainsX(window, p.x()) && p.y() == 0) |
- return window; |
- break; |
- case HTBOTTOM: |
- if (ContainsX(window, p.x()) && p.y() == window->GetBounds().height()) |
- return window; |
- break; |
- default: |
- NOTREACHED(); |
- } |
- // Window doesn't contain the edge, but if window contains |point| |
- // it's obscuring any other window that could be at the location. |
- if (window->GetBounds().Contains(x_in_parent, y_in_parent)) |
- return NULL; |
- } |
- return NULL; |
-} |
- |
-WmWindow* MultiWindowResizeController::FindWindowTouching( |
- WmWindow* window, |
- Direction direction) const { |
- int right = window->GetBounds().right(); |
- int bottom = window->GetBounds().bottom(); |
- WmWindow* parent = window->GetParent(); |
- std::vector<WmWindow*> windows = parent->GetChildren(); |
- for (auto i = windows.rbegin(); i != windows.rend(); ++i) { |
- WmWindow* other = *i; |
- if (other == window || !other->IsVisible()) |
- continue; |
- switch (direction) { |
- case TOP_BOTTOM: |
- if (other->GetBounds().y() == bottom && |
- Intersects(other->GetBounds().x(), other->GetBounds().right(), |
- window->GetBounds().x(), window->GetBounds().right())) { |
- return other; |
- } |
- break; |
- case LEFT_RIGHT: |
- if (other->GetBounds().x() == right && |
- Intersects(other->GetBounds().y(), other->GetBounds().bottom(), |
- window->GetBounds().y(), window->GetBounds().bottom())) { |
- return other; |
- } |
- break; |
- default: |
- NOTREACHED(); |
- } |
- } |
- return NULL; |
-} |
- |
-void MultiWindowResizeController::FindWindowsTouching( |
- WmWindow* start, |
- Direction direction, |
- std::vector<WmWindow*>* others) const { |
- while (start) { |
- start = FindWindowTouching(start, direction); |
- if (start) |
- others->push_back(start); |
- } |
-} |
- |
-void MultiWindowResizeController::ShowIfValidMouseLocation() { |
- if (DetermineWindowsFromScreenPoint(windows_.window1).Equals(windows_) || |
- DetermineWindowsFromScreenPoint(windows_.window2).Equals(windows_)) { |
- ShowNow(); |
- } else { |
- Hide(); |
- } |
-} |
- |
-void MultiWindowResizeController::ShowNow() { |
- DCHECK(!resize_widget_.get()); |
- DCHECK(windows_.is_valid()); |
- show_timer_.Stop(); |
- resize_widget_.reset(new views::Widget); |
- views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); |
- params.name = "MultiWindowResizeController"; |
- params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; |
- params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
- windows_.window1->GetRootWindowController() |
- ->ConfigureWidgetInitParamsForContainer( |
- resize_widget_.get(), kShellWindowId_AlwaysOnTopContainer, ¶ms); |
- ResizeView* view = new ResizeView(this, windows_.direction); |
- resize_widget_->set_focus_on_creation(false); |
- resize_widget_->Init(params); |
- WmWindow::Get(resize_widget_->GetNativeWindow()) |
- ->SetVisibilityAnimationType(::wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); |
- resize_widget_->SetContentsView(view); |
- show_bounds_in_screen_ = windows_.window1->GetParent()->ConvertRectToScreen( |
- CalculateResizeWidgetBounds(show_location_in_parent_)); |
- resize_widget_->SetBounds(show_bounds_in_screen_); |
- resize_widget_->Show(); |
- CreateMouseWatcher(); |
-} |
- |
-bool MultiWindowResizeController::IsShowing() const { |
- return resize_widget_.get() || show_timer_.IsRunning(); |
-} |
- |
-void MultiWindowResizeController::StartResize( |
- const gfx::Point& location_in_screen) { |
- DCHECK(!window_resizer_.get()); |
- DCHECK(windows_.is_valid()); |
- gfx::Point location_in_parent = |
- windows_.window2->GetParent()->ConvertPointFromScreen(location_in_screen); |
- std::vector<WmWindow*> windows; |
- windows.push_back(windows_.window2); |
- DCHECK(windows_.other_windows.empty()); |
- FindWindowsTouching(windows_.window2, windows_.direction, |
- &windows_.other_windows); |
- for (size_t i = 0; i < windows_.other_windows.size(); ++i) { |
- windows_.other_windows[i]->aura_window()->AddObserver(this); |
- windows.push_back(windows_.other_windows[i]); |
- } |
- int component = windows_.direction == LEFT_RIGHT ? HTRIGHT : HTBOTTOM; |
- wm::WindowState* window_state = windows_.window1->GetWindowState(); |
- window_state->CreateDragDetails(location_in_parent, component, |
- aura::client::WINDOW_MOVE_SOURCE_MOUSE); |
- window_resizer_.reset(WorkspaceWindowResizer::Create(window_state, windows)); |
- |
- // Do not hide the resize widget while a drag is active. |
- mouse_watcher_.reset(); |
-} |
- |
-void MultiWindowResizeController::Resize(const gfx::Point& location_in_screen, |
- int event_flags) { |
- gfx::Point location_in_parent = |
- windows_.window1->GetParent()->ConvertPointFromScreen(location_in_screen); |
- window_resizer_->Drag(location_in_parent, event_flags); |
- gfx::Rect bounds = windows_.window1->GetParent()->ConvertRectToScreen( |
- CalculateResizeWidgetBounds(location_in_parent)); |
- |
- if (windows_.direction == LEFT_RIGHT) |
- bounds.set_y(show_bounds_in_screen_.y()); |
- else |
- bounds.set_x(show_bounds_in_screen_.x()); |
- resize_widget_->SetBounds(bounds); |
-} |
- |
-void MultiWindowResizeController::CompleteResize() { |
- window_resizer_->CompleteDrag(); |
- window_resizer_->GetTarget()->GetWindowState()->DeleteDragDetails(); |
- window_resizer_.reset(); |
- |
- // Mouse may still be over resizer, if not hide. |
- gfx::Point screen_loc = display::Screen::GetScreen()->GetCursorScreenPoint(); |
- if (!resize_widget_->GetWindowBoundsInScreen().Contains(screen_loc)) { |
- Hide(); |
- } else { |
- // If the mouse is over the resizer we need to remove observers on any of |
- // the |other_windows|. If we start another resize we'll recalculate the |
- // |other_windows| and invoke AddObserver() as necessary. |
- for (size_t i = 0; i < windows_.other_windows.size(); ++i) |
- windows_.other_windows[i]->aura_window()->RemoveObserver(this); |
- windows_.other_windows.clear(); |
- |
- CreateMouseWatcher(); |
- } |
-} |
- |
-void MultiWindowResizeController::CancelResize() { |
- if (!window_resizer_) |
- return; // Happens if window was destroyed and we nuked the WindowResizer. |
- window_resizer_->RevertDrag(); |
- window_resizer_->GetTarget()->GetWindowState()->DeleteDragDetails(); |
- window_resizer_.reset(); |
- Hide(); |
-} |
- |
-gfx::Rect MultiWindowResizeController::CalculateResizeWidgetBounds( |
- const gfx::Point& location_in_parent) const { |
- gfx::Size pref = resize_widget_->GetContentsView()->GetPreferredSize(); |
- int x = 0, y = 0; |
- if (windows_.direction == LEFT_RIGHT) { |
- x = windows_.window1->GetBounds().right() - pref.width() / 2; |
- y = location_in_parent.y() + kResizeWidgetPadding; |
- if (y + pref.height() / 2 > windows_.window1->GetBounds().bottom() && |
- y + pref.height() / 2 > windows_.window2->GetBounds().bottom()) { |
- y = location_in_parent.y() - kResizeWidgetPadding - pref.height(); |
- } |
- } else { |
- x = location_in_parent.x() + kResizeWidgetPadding; |
- if (x + pref.height() / 2 > windows_.window1->GetBounds().right() && |
- x + pref.height() / 2 > windows_.window2->GetBounds().right()) { |
- x = location_in_parent.x() - kResizeWidgetPadding - pref.width(); |
- } |
- y = windows_.window1->GetBounds().bottom() - pref.height() / 2; |
- } |
- return gfx::Rect(x, y, pref.width(), pref.height()); |
-} |
- |
-bool MultiWindowResizeController::IsOverResizeWidget( |
- const gfx::Point& location_in_screen) const { |
- return resize_widget_->GetWindowBoundsInScreen().Contains(location_in_screen); |
-} |
- |
-bool MultiWindowResizeController::IsOverWindows( |
- const gfx::Point& location_in_screen) const { |
- if (IsOverResizeWidget(location_in_screen)) |
- return true; |
- |
- if (windows_.direction == TOP_BOTTOM) { |
- if (!ContainsScreenX(windows_.window1, location_in_screen.x()) || |
- !ContainsScreenX(windows_.window2, location_in_screen.x())) { |
- return false; |
- } |
- } else { |
- if (!ContainsScreenY(windows_.window1, location_in_screen.y()) || |
- !ContainsScreenY(windows_.window2, location_in_screen.y())) { |
- return false; |
- } |
- } |
- |
- // Check whether |location_in_screen| is in the event target's resize region. |
- // This is tricky because a window's resize region can extend outside a |
- // window's bounds. |
- WmWindow* target = |
- windows_.window1->GetRootWindowController()->FindEventTarget( |
- location_in_screen); |
- if (target == windows_.window1) { |
- return IsOverComponent( |
- windows_.window1, location_in_screen, |
- windows_.direction == TOP_BOTTOM ? HTBOTTOM : HTRIGHT); |
- } |
- if (target == windows_.window2) { |
- return IsOverComponent(windows_.window2, location_in_screen, |
- windows_.direction == TOP_BOTTOM ? HTTOP : HTLEFT); |
- } |
- return false; |
-} |
- |
-bool MultiWindowResizeController::IsOverComponent( |
- WmWindow* window, |
- const gfx::Point& location_in_screen, |
- int component) const { |
- gfx::Point window_loc = window->ConvertPointFromScreen(location_in_screen); |
- return window->GetNonClientComponent(window_loc) == component; |
-} |
- |
-} // namespace ash |