15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/workspace/multi_window_resize_controller.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/screen_ash.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell_window_ids.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/coordinate_conversion.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/window_animations.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/workspace/workspace_event_handler.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/wm/workspace/workspace_window_resizer.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ash_resources.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/client/screen_position_client.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/root_window.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window_delegate.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/hit_test.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/corewm/compound_event_filter.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/view.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget_delegate.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using aura::Window; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Delay before showing. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kShowDelayMS = 400; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Delay before hiding. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kHideDelayMS = 500; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Padding from the bottom/right edge the resize widget is shown at. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kResizeWidgetPadding = 15; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ContainsX(Window* window, int x) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return window->bounds().x() <= x && window->bounds().right() >= x; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ContainsY(Window* window, int y) { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return window->bounds().y() <= y && window->bounds().bottom() >= y; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Intersects(int x1, int max_1, int x2, int max_2) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return x2 <= max_1 && max_2 > x1; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// View contained in the widget. Passes along mouse events to the 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MultiWindowResizeController so that it can start/stop the resize loop. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MultiWindowResizeController::ResizeView : public views::View { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit ResizeView(MultiWindowResizeController* controller, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Direction direction) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : controller_(controller), 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) direction_(direction), 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_(NULL) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int image_id = 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) direction == TOP_BOTTOM ? IDR_AURA_MULTI_WINDOW_RESIZE_H : 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_AURA_MULTI_WINDOW_RESIZE_V; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_ = rb.GetImageNamed(image_id).ToImageSkia(); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views::View overrides: 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual gfx::Size GetPreferredSize() OVERRIDE { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gfx::Size(image_->width(), image_->height()); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->DrawImageInt(*image_, 0, 0); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point location(event.location()); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View::ConvertPointToScreen(this, &location); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) controller_->StartResize(location); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point location(event.location()); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View::ConvertPointToScreen(this, &location); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) controller_->Resize(location, event.flags()); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) controller_->CompleteResize(event.flags()); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnMouseCaptureLost() OVERRIDE { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) controller_->CancelResize(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual gfx::NativeCursor GetCursor( 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::MouseEvent& event) OVERRIDE { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int component = (direction_ == LEFT_RIGHT) ? HTRIGHT : HTBOTTOM; 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return views::corewm::CompoundEventFilter::CursorForWindowComponent( 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) component); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MultiWindowResizeController* controller_; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Direction direction_; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::ImageSkia* image_; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ResizeView); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MouseWatcherHost implementation for MultiWindowResizeController. Forwards 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Contains() to MultiWindowResizeController. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MultiWindowResizeController::ResizeMouseWatcherHost : 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public views::MouseWatcherHost { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResizeMouseWatcherHost(MultiWindowResizeController* host) : host_(host) {} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // MouseWatcherHost overrides: 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool Contains(const gfx::Point& point_in_screen, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MouseEventType type) OVERRIDE { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return host_->IsOverWindows(point_in_screen); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MultiWindowResizeController* host_; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ResizeMouseWatcherHost); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MultiWindowResizeController::ResizeWindows::ResizeWindows() 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : window1(NULL), 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window2(NULL), 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) direction(TOP_BOTTOM){ 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MultiWindowResizeController::ResizeWindows::~ResizeWindows() { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MultiWindowResizeController::ResizeWindows::Equals( 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ResizeWindows& other) const { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return window1 == other.window1 && 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window2 == other.window2 && 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) direction == other.direction; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MultiWindowResizeController::MultiWindowResizeController() { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MultiWindowResizeController::~MultiWindowResizeController() { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_resizer_.reset(); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Hide(); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MultiWindowResizeController::Show(Window* window, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int component, 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point_in_window) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When the resize widget is showing we ignore Show() requests. Instead we 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // only care about mouse movements from MouseWatcher. This is necessary as 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WorkspaceEventHandler only sees mouse movements over the windows, not all 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // windows or over the desktop. 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (resize_widget_) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResizeWindows windows(DetermineWindows(window, component, point_in_window)); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsShowing()) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (windows_.Equals(windows)) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // Over the same windows. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DelayedHide(); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!windows.is_valid()) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Hide(); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows_ = windows; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows_.window1->AddObserver(this); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows_.window2->AddObserver(this); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) show_location_in_parent_ = point_in_window; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Window::ConvertPointToTarget( 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window, window->parent(), &show_location_in_parent_); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (show_timer_.IsRunning()) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) show_timer_.Start( 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::TimeDelta::FromMilliseconds(kShowDelayMS), 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, &MultiWindowResizeController::ShowIfValidMouseLocation); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MultiWindowResizeController::Hide() { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hide_timer_.Stop(); 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (window_resizer_) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // Ignore hides while actively resizing. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (windows_.window1) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows_.window1->RemoveObserver(this); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows_.window1 = NULL; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (windows_.window2) { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows_.window2->RemoveObserver(this); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows_.window2 = NULL; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) show_timer_.Stop(); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!resize_widget_) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < windows_.other_windows.size(); ++i) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows_.other_windows[i]->RemoveObserver(this); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_watcher_.reset(); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_widget_.reset(); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows_ = ResizeWindows(); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MultiWindowResizeController::MouseMovedOutOfHost() { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Hide(); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MultiWindowResizeController::OnWindowDestroying( 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aura::Window* window) { 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Have to explicitly reset the WindowResizer, otherwise Hide() does nothing. 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_resizer_.reset(); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Hide(); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MultiWindowResizeController::ResizeWindows 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MultiWindowResizeController::DetermineWindowsFromScreenPoint( 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aura::Window* window) const { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point mouse_location( 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Screen::GetScreenFor(window)->GetCursorScreenPoint()); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wm::ConvertPointFromScreen(window, &mouse_location); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int component = 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window->delegate()->GetNonClientComponent(mouse_location); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DetermineWindows(window, component, mouse_location); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MultiWindowResizeController::ResizeWindows 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MultiWindowResizeController::DetermineWindows( 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Window* window, 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int window_component, 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point) const { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResizeWindows result; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point point_in_parent(point); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Window::ConvertPointToTarget(window, window->parent(), &point_in_parent); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (window_component) { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HTRIGHT: 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.direction = LEFT_RIGHT; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.window1 = window; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.window2 = FindWindowByEdge( 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window, HTLEFT, window->bounds().right(), point_in_parent.y()); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HTLEFT: 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.direction = LEFT_RIGHT; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.window1 = FindWindowByEdge( 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window, HTRIGHT, window->bounds().x(), point_in_parent.y()); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.window2 = window; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HTTOP: 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.direction = TOP_BOTTOM; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.window1 = FindWindowByEdge( 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window, HTBOTTOM, point_in_parent.x(), window->bounds().y()); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.window2 = window; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HTBOTTOM: 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.direction = TOP_BOTTOM; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.window1 = window; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.window2 = FindWindowByEdge( 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window, HTTOP, point_in_parent.x(), window->bounds().bottom()); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Window* MultiWindowResizeController::FindWindowByEdge( 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Window* window_to_ignore, 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int edge_want, 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x, 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y) const { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Window* parent = window_to_ignore->parent(); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Window::Windows& windows(parent->children()); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Window::Windows::const_reverse_iterator i = windows.rbegin(); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != windows.rend(); ++i) { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Window* window = *i; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (window == window_to_ignore || !window->IsVisible()) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (edge_want) { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HTLEFT: 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ContainsY(window, y) && window->bounds().x() == x) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return window; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HTRIGHT: 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ContainsY(window, y) && window->bounds().right() == x) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return window; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HTTOP: 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ContainsX(window, x) && window->bounds().y() == y) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return window; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HTBOTTOM: 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ContainsX(window, x) && window->bounds().bottom() == y) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return window; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Window doesn't contain the edge, but if window contains |point| 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it's obscuring any other window that could be at the location. 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (window->bounds().Contains(x, y)) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)aura::Window* MultiWindowResizeController::FindWindowTouching( 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aura::Window* window, 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Direction direction) const { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int right = window->bounds().right(); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bottom = window->bounds().bottom(); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Window* parent = window->parent(); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Window::Windows& windows(parent->children()); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Window::Windows::const_reverse_iterator i = windows.rbegin(); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != windows.rend(); ++i) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Window* other = *i; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (other == window || !other->IsVisible()) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (direction) { 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case TOP_BOTTOM: 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (other->bounds().y() == bottom && 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Intersects(other->bounds().x(), other->bounds().right(), 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window->bounds().x(), window->bounds().right())) { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return other; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LEFT_RIGHT: 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (other->bounds().x() == right && 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Intersects(other->bounds().y(), other->bounds().bottom(), 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window->bounds().y(), window->bounds().bottom())) { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return other; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MultiWindowResizeController::FindWindowsTouching( 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aura::Window* start, 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Direction direction, 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<aura::Window*>* others) const { 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (start) { 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start = FindWindowTouching(start, direction); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (start) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) others->push_back(start); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MultiWindowResizeController::DelayedHide() { 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hide_timer_.IsRunning()) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hide_timer_.Start(FROM_HERE, 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kHideDelayMS), 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, &MultiWindowResizeController::Hide); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MultiWindowResizeController::ShowIfValidMouseLocation() { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (DetermineWindowsFromScreenPoint(windows_.window1).Equals(windows_) || 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DetermineWindowsFromScreenPoint(windows_.window2).Equals(windows_)) { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShowNow(); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Hide(); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MultiWindowResizeController::ShowNow() { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!resize_widget_.get()); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(windows_.is_valid()); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) show_timer_.Stop(); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_widget_.reset(new views::Widget); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); 387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.parent = Shell::GetContainer( 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Shell::GetActiveRootWindow(), 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) internal::kShellWindowId_AlwaysOnTopContainer); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.can_activate = false; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResizeView* view = new ResizeView(this, windows_.direction); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_widget_->set_focus_on_creation(false); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_widget_->Init(params); 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::corewm::SetWindowVisibilityAnimationType( 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_widget_->GetNativeWindow(), 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_widget_->GetNativeWindow()->SetName("MultiWindowResizeController"); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_widget_->SetContentsView(view); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) show_bounds_in_screen_ = ScreenAsh::ConvertRectToScreen( 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows_.window1->parent(), 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CalculateResizeWidgetBounds(show_location_in_parent_)); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_widget_->SetBounds(show_bounds_in_screen_); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_widget_->Show(); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_watcher_.reset(new views::MouseWatcher( 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ResizeMouseWatcherHost(this), 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this)); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_watcher_->set_notify_on_exit_time( 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kHideDelayMS)); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mouse_watcher_->Start(); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MultiWindowResizeController::IsShowing() const { 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return resize_widget_.get() || show_timer_.IsRunning(); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MultiWindowResizeController::StartResize( 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& location_in_screen) { 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!window_resizer_.get()); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(windows_.is_valid()); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hide_timer_.Stop(); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point location_in_parent(location_in_screen); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aura::client::GetScreenPositionClient(windows_.window2->GetRootWindow())-> 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConvertPointFromScreen(windows_.window2->parent(), &location_in_parent); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<aura::Window*> windows; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows.push_back(windows_.window2); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(windows_.other_windows.empty()); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FindWindowsTouching(windows_.window2, windows_.direction, 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &windows_.other_windows); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < windows_.other_windows.size(); ++i) { 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows_.other_windows[i]->AddObserver(this); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows.push_back(windows_.other_windows[i]); 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int component = windows_.direction == LEFT_RIGHT ? HTRIGHT : HTBOTTOM; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_resizer_.reset(WorkspaceWindowResizer::Create( 4377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) windows_.window1, 4387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) location_in_parent, 4397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) component, 4407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) aura::client::WINDOW_MOVE_SOURCE_MOUSE, 4417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) windows)); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MultiWindowResizeController::Resize(const gfx::Point& location_in_screen, 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int event_flags) { 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point location_in_parent(location_in_screen); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aura::client::GetScreenPositionClient(windows_.window1->GetRootWindow())-> 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConvertPointFromScreen(windows_.window1->parent(), &location_in_parent); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_resizer_->Drag(location_in_parent, event_flags); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect bounds = ScreenAsh::ConvertRectToScreen( 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows_.window1->parent(), 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CalculateResizeWidgetBounds(location_in_parent)); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (windows_.direction == LEFT_RIGHT) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bounds.set_y(show_bounds_in_screen_.y()); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bounds.set_x(show_bounds_in_screen_.x()); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_widget_->SetBounds(bounds); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MultiWindowResizeController::CompleteResize(int event_flags) { 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_resizer_->CompleteDrag(event_flags); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_resizer_.reset(); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mouse may still be over resizer, if not hide. 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point screen_loc = Shell::GetScreen()->GetCursorScreenPoint(); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!resize_widget_->GetWindowBoundsInScreen().Contains(screen_loc)) { 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Hide(); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the mouse is over the resizer we need to remove observers on any of 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the |other_windows|. If we start another resize we'll recalculate the 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |other_windows| and invoke AddObserver() as necessary. 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < windows_.other_windows.size(); ++i) 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows_.other_windows[i]->RemoveObserver(this); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windows_.other_windows.clear(); 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MultiWindowResizeController::CancelResize() { 480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!window_resizer_) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // Happens if window was destroyed and we nuked the WindowResizer. 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_resizer_->RevertDrag(); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_resizer_.reset(); 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Hide(); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gfx::Rect MultiWindowResizeController::CalculateResizeWidgetBounds( 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& location_in_parent) const { 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size pref = resize_widget_->GetContentsView()->GetPreferredSize(); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x = 0, y = 0; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (windows_.direction == LEFT_RIGHT) { 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x = windows_.window1->bounds().right() - pref.width() / 2; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y = location_in_parent.y() + kResizeWidgetPadding; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (y + pref.height() / 2 > windows_.window1->bounds().bottom() && 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y + pref.height() / 2 > windows_.window2->bounds().bottom()) { 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y = location_in_parent.y() - kResizeWidgetPadding - pref.height(); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x = location_in_parent.x() + kResizeWidgetPadding; 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (x + pref.height() / 2 > windows_.window1->bounds().right() && 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x + pref.height() / 2 > windows_.window2->bounds().right()) { 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x = location_in_parent.x() - kResizeWidgetPadding - pref.width(); 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y = windows_.window1->bounds().bottom() - pref.height() / 2; 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gfx::Rect(x, y, pref.width(), pref.height()); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MultiWindowResizeController::IsOverWindows( 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& location_in_screen) const { 511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (window_resizer_) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; // Ignore hides while actively resizing. 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (resize_widget_->GetWindowBoundsInScreen().Contains(location_in_screen)) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int hit1, hit2; 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (windows_.direction == TOP_BOTTOM) { 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hit1 = HTBOTTOM; 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hit2 = HTTOP; 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hit1 = HTRIGHT; 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hit2 = HTLEFT; 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return IsOverWindow(windows_.window1, location_in_screen, hit1) || 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsOverWindow(windows_.window2, location_in_screen, hit2); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MultiWindowResizeController::IsOverWindow( 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aura::Window* window, 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& location_in_screen, 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int component) const { 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!window->delegate()) 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point window_loc(location_in_screen); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aura::Window::ConvertPointToTarget( 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window->GetRootWindow(), window, &window_loc); 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return window->HitTest(window_loc) && 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window->delegate()->GetNonClientComponent(window_loc) == component; 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace internal 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace ash 546