diff options
Diffstat (limited to 'chromium/ash/wm/workspace/multi_window_resize_controller.cc')
-rw-r--r-- | chromium/ash/wm/workspace/multi_window_resize_controller.cc | 545 |
1 files changed, 0 insertions, 545 deletions
diff --git a/chromium/ash/wm/workspace/multi_window_resize_controller.cc b/chromium/ash/wm/workspace/multi_window_resize_controller.cc deleted file mode 100644 index 597acbf88ec..00000000000 --- a/chromium/ash/wm/workspace/multi_window_resize_controller.cc +++ /dev/null @@ -1,545 +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/wm/workspace/multi_window_resize_controller.h" - -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/coordinate_conversion.h" -#include "ash/wm/window_animations.h" -#include "ash/wm/workspace/workspace_event_handler.h" -#include "ash/wm/workspace/workspace_window_resizer.h" -#include "grit/ash_resources.h" -#include "ui/aura/client/screen_position_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/screen.h" -#include "ui/views/corewm/compound_event_filter.h" -#include "ui/views/view.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -using aura::Window; - -namespace ash { -namespace internal { - -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(Window* window, int x) { - return window->bounds().x() <= x && window->bounds().right() >= x; -} - -bool ContainsY(Window* window, int y) { - return window->bounds().y() <= y && window->bounds().bottom() >= 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: - virtual gfx::Size GetPreferredSize() OVERRIDE { - return gfx::Size(image_->width(), image_->height()); - } - virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { - canvas->DrawImageInt(*image_, 0, 0); - } - virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE { - gfx::Point location(event.location()); - views::View::ConvertPointToScreen(this, &location); - controller_->StartResize(location); - return true; - } - virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE { - gfx::Point location(event.location()); - views::View::ConvertPointToScreen(this, &location); - controller_->Resize(location, event.flags()); - return true; - } - virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE { - controller_->CompleteResize(event.flags()); - } - virtual void OnMouseCaptureLost() OVERRIDE { - controller_->CancelResize(); - } - virtual gfx::NativeCursor GetCursor( - const ui::MouseEvent& event) OVERRIDE { - int component = (direction_ == LEFT_RIGHT) ? HTRIGHT : HTBOTTOM; - return views::corewm::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: - virtual bool Contains(const gfx::Point& point_in_screen, - MouseEventType type) OVERRIDE { - return host_->IsOverWindows(point_in_screen); - } - - private: - MultiWindowResizeController* host_; - - DISALLOW_COPY_AND_ASSIGN(ResizeMouseWatcherHost); -}; - -MultiWindowResizeController::ResizeWindows::ResizeWindows() - : window1(NULL), - window2(NULL), - direction(TOP_BOTTOM){ -} - -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(Window* 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()) { - if (windows_.Equals(windows)) - return; // Over the same windows. - DelayedHide(); - } - - if (!windows.is_valid()) - return; - Hide(); - windows_ = windows; - windows_.window1->AddObserver(this); - windows_.window2->AddObserver(this); - show_location_in_parent_ = point_in_window; - Window::ConvertPointToTarget( - window, window->parent(), &show_location_in_parent_); - if (show_timer_.IsRunning()) - return; - show_timer_.Start( - FROM_HERE, base::TimeDelta::FromMilliseconds(kShowDelayMS), - this, &MultiWindowResizeController::ShowIfValidMouseLocation); -} - -void MultiWindowResizeController::Hide() { - hide_timer_.Stop(); - if (window_resizer_) - return; // Ignore hides while actively resizing. - - if (windows_.window1) { - windows_.window1->RemoveObserver(this); - windows_.window1 = NULL; - } - if (windows_.window2) { - windows_.window2->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]->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( - aura::Window* window) const { - gfx::Point mouse_location( - gfx::Screen::GetScreenFor(window)->GetCursorScreenPoint()); - wm::ConvertPointFromScreen(window, &mouse_location); - const int component = - window->delegate()->GetNonClientComponent(mouse_location); - return DetermineWindows(window, component, mouse_location); -} - -MultiWindowResizeController::ResizeWindows -MultiWindowResizeController::DetermineWindows( - Window* window, - int window_component, - const gfx::Point& point) const { - ResizeWindows result; - gfx::Point point_in_parent(point); - Window::ConvertPointToTarget(window, window->parent(), &point_in_parent); - switch (window_component) { - case HTRIGHT: - result.direction = LEFT_RIGHT; - result.window1 = window; - result.window2 = FindWindowByEdge( - window, HTLEFT, window->bounds().right(), point_in_parent.y()); - break; - case HTLEFT: - result.direction = LEFT_RIGHT; - result.window1 = FindWindowByEdge( - window, HTRIGHT, window->bounds().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->bounds().y()); - result.window2 = window; - break; - case HTBOTTOM: - result.direction = TOP_BOTTOM; - result.window1 = window; - result.window2 = FindWindowByEdge( - window, HTTOP, point_in_parent.x(), window->bounds().bottom()); - break; - default: - break; - } - return result; -} - -Window* MultiWindowResizeController::FindWindowByEdge( - Window* window_to_ignore, - int edge_want, - int x, - int y) const { - Window* parent = window_to_ignore->parent(); - const Window::Windows& windows(parent->children()); - for (Window::Windows::const_reverse_iterator i = windows.rbegin(); - i != windows.rend(); ++i) { - Window* window = *i; - if (window == window_to_ignore || !window->IsVisible()) - continue; - switch (edge_want) { - case HTLEFT: - if (ContainsY(window, y) && window->bounds().x() == x) - return window; - break; - case HTRIGHT: - if (ContainsY(window, y) && window->bounds().right() == x) - return window; - break; - case HTTOP: - if (ContainsX(window, x) && window->bounds().y() == y) - return window; - break; - case HTBOTTOM: - if (ContainsX(window, x) && window->bounds().bottom() == y) - 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->bounds().Contains(x, y)) - return NULL; - } - return NULL; -} - -aura::Window* MultiWindowResizeController::FindWindowTouching( - aura::Window* window, - Direction direction) const { - int right = window->bounds().right(); - int bottom = window->bounds().bottom(); - Window* parent = window->parent(); - const Window::Windows& windows(parent->children()); - for (Window::Windows::const_reverse_iterator i = windows.rbegin(); - i != windows.rend(); ++i) { - Window* other = *i; - if (other == window || !other->IsVisible()) - continue; - switch (direction) { - case TOP_BOTTOM: - if (other->bounds().y() == bottom && - Intersects(other->bounds().x(), other->bounds().right(), - window->bounds().x(), window->bounds().right())) { - return other; - } - break; - case LEFT_RIGHT: - if (other->bounds().x() == right && - Intersects(other->bounds().y(), other->bounds().bottom(), - window->bounds().y(), window->bounds().bottom())) { - return other; - } - break; - default: - NOTREACHED(); - } - } - return NULL; -} - -void MultiWindowResizeController::FindWindowsTouching( - aura::Window* start, - Direction direction, - std::vector<aura::Window*>* others) const { - while (start) { - start = FindWindowTouching(start, direction); - if (start) - others->push_back(start); - } -} - -void MultiWindowResizeController::DelayedHide() { - if (hide_timer_.IsRunning()) - return; - - hide_timer_.Start(FROM_HERE, - base::TimeDelta::FromMilliseconds(kHideDelayMS), - this, &MultiWindowResizeController::Hide); -} - -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.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.parent = Shell::GetContainer( - Shell::GetTargetRootWindow(), - internal::kShellWindowId_AlwaysOnTopContainer); - params.can_activate = false; - ResizeView* view = new ResizeView(this, windows_.direction); - resize_widget_->set_focus_on_creation(false); - resize_widget_->Init(params); - views::corewm::SetWindowVisibilityAnimationType( - resize_widget_->GetNativeWindow(), - views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); - resize_widget_->GetNativeWindow()->SetName("MultiWindowResizeController"); - resize_widget_->SetContentsView(view); - show_bounds_in_screen_ = ScreenAsh::ConvertRectToScreen( - windows_.window1->parent(), - CalculateResizeWidgetBounds(show_location_in_parent_)); - resize_widget_->SetBounds(show_bounds_in_screen_); - resize_widget_->Show(); - mouse_watcher_.reset(new views::MouseWatcher( - new ResizeMouseWatcherHost(this), - this)); - mouse_watcher_->set_notify_on_exit_time( - base::TimeDelta::FromMilliseconds(kHideDelayMS)); - mouse_watcher_->Start(); -} - -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()); - hide_timer_.Stop(); - gfx::Point location_in_parent(location_in_screen); - aura::client::GetScreenPositionClient(windows_.window2->GetRootWindow())-> - ConvertPointFromScreen(windows_.window2->parent(), &location_in_parent); - std::vector<aura::Window*> 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]->AddObserver(this); - windows.push_back(windows_.other_windows[i]); - } - int component = windows_.direction == LEFT_RIGHT ? HTRIGHT : HTBOTTOM; - window_resizer_.reset(WorkspaceWindowResizer::Create( - windows_.window1, - location_in_parent, - component, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, - windows)); -} - -void MultiWindowResizeController::Resize(const gfx::Point& location_in_screen, - int event_flags) { - gfx::Point location_in_parent(location_in_screen); - aura::client::GetScreenPositionClient(windows_.window1->GetRootWindow())-> - ConvertPointFromScreen(windows_.window1->parent(), &location_in_parent); - window_resizer_->Drag(location_in_parent, event_flags); - gfx::Rect bounds = ScreenAsh::ConvertRectToScreen( - windows_.window1->parent(), - 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(int event_flags) { - window_resizer_->CompleteDrag(event_flags); - window_resizer_.reset(); - - // Mouse may still be over resizer, if not hide. - gfx::Point screen_loc = Shell::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]->RemoveObserver(this); - windows_.other_windows.clear(); - } -} - -void MultiWindowResizeController::CancelResize() { - if (!window_resizer_) - return; // Happens if window was destroyed and we nuked the WindowResizer. - window_resizer_->RevertDrag(); - 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->bounds().right() - pref.width() / 2; - y = location_in_parent.y() + kResizeWidgetPadding; - if (y + pref.height() / 2 > windows_.window1->bounds().bottom() && - y + pref.height() / 2 > windows_.window2->bounds().bottom()) { - y = location_in_parent.y() - kResizeWidgetPadding - pref.height(); - } - } else { - x = location_in_parent.x() + kResizeWidgetPadding; - if (x + pref.height() / 2 > windows_.window1->bounds().right() && - x + pref.height() / 2 > windows_.window2->bounds().right()) { - x = location_in_parent.x() - kResizeWidgetPadding - pref.width(); - } - y = windows_.window1->bounds().bottom() - pref.height() / 2; - } - return gfx::Rect(x, y, pref.width(), pref.height()); -} - -bool MultiWindowResizeController::IsOverWindows( - const gfx::Point& location_in_screen) const { - if (window_resizer_) - return true; // Ignore hides while actively resizing. - - if (resize_widget_->GetWindowBoundsInScreen().Contains(location_in_screen)) - return true; - - int hit1, hit2; - if (windows_.direction == TOP_BOTTOM) { - hit1 = HTBOTTOM; - hit2 = HTTOP; - } else { - hit1 = HTRIGHT; - hit2 = HTLEFT; - } - - return IsOverWindow(windows_.window1, location_in_screen, hit1) || - IsOverWindow(windows_.window2, location_in_screen, hit2); -} - -bool MultiWindowResizeController::IsOverWindow( - aura::Window* window, - const gfx::Point& location_in_screen, - int component) const { - if (!window->delegate()) - return false; - - gfx::Point window_loc(location_in_screen); - aura::Window::ConvertPointToTarget( - window->GetRootWindow(), window, &window_loc); - return window->HitTest(window_loc) && - window->delegate()->GetNonClientComponent(window_loc) == component; -} - -} // namespace internal -} // namespace ash |