| Index: ash/wm/drag_window_resizer.cc
|
| diff --git a/ash/wm/drag_window_resizer.cc b/ash/wm/drag_window_resizer.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..2b85f814a4d7b1264c194c81e0e9a72b4439b768
|
| --- /dev/null
|
| +++ b/ash/wm/drag_window_resizer.cc
|
| @@ -0,0 +1,185 @@
|
| +// 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/drag_window_resizer.h"
|
| +
|
| +#include "ash/display/mouse_cursor_event_filter.h"
|
| +#include "ash/screen_ash.h"
|
| +#include "ash/shell.h"
|
| +#include "ash/wm/coordinate_conversion.h"
|
| +#include "ash/wm/cursor_manager.h"
|
| +#include "ash/wm/drag_window_controller.h"
|
| +#include "ash/wm/property_util.h"
|
| +#include "ui/aura/client/aura_constants.h"
|
| +#include "ui/aura/env.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/ui_base_types.h"
|
| +#include "ui/gfx/screen.h"
|
| +
|
| +namespace ash {
|
| +namespace internal {
|
| +
|
| +namespace {
|
| +
|
| +// The maximum opacity of the drag phantom window.
|
| +const float kMaxOpacity = 0.8f;
|
| +
|
| +// Returns true if Ash has more than one root window.
|
| +bool HasSecondaryRootWindow() {
|
| + return Shell::GetAllRootWindows().size() > 1;
|
| +}
|
| +
|
| +// When there are two root windows, returns one of the root windows which is not
|
| +// |root_window|. Returns NULL if only one root window exists.
|
| +aura::RootWindow* GetAnotherRootWindow(aura::RootWindow* root_window) {
|
| + Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
|
| + if (root_windows.size() < 2)
|
| + return NULL;
|
| + DCHECK_EQ(2U, root_windows.size());
|
| + if (root_windows[0] == root_window)
|
| + return root_windows[1];
|
| + return root_windows[0];
|
| +}
|
| +
|
| +}
|
| +
|
| +DragWindowResizer::DragWindowResizer(WindowResizer* window_resizer,
|
| + const Details& details)
|
| + : window_resizer_(window_resizer),
|
| + details_(details),
|
| + destroyed_(NULL) {
|
| + // The pointer should be confined in one display during resizing a window
|
| + // because the window cannot span two displays at the same time anyway. The
|
| + // exception is window/tab dragging operation. During that operation,
|
| + // |mouse_warp_mode_| should be set to WARP_DRAG so that the user could move a
|
| + // window/tab to another display.
|
| + MouseCursorEventFilter* mouse_cursor_filter =
|
| + Shell::GetInstance()->mouse_cursor_filter();
|
| + mouse_cursor_filter->set_mouse_warp_mode(
|
| + ShouldAllowMouseWarp() ?
|
| + MouseCursorEventFilter::WARP_DRAG : MouseCursorEventFilter::WARP_NONE);
|
| + if (ShouldAllowMouseWarp()) {
|
| + mouse_cursor_filter->ShowSharedEdgeIndicator(
|
| + details.window->GetRootWindow());
|
| + }
|
| +}
|
| +
|
| +DragWindowResizer::~DragWindowResizer() {
|
| + Shell* shell = Shell::GetInstance();
|
| + shell->mouse_cursor_filter()->set_mouse_warp_mode(
|
| + MouseCursorEventFilter::WARP_ALWAYS);
|
| + shell->mouse_cursor_filter()->HideSharedEdgeIndicator();
|
| +
|
| + if (destroyed_)
|
| + *destroyed_ = true;
|
| +}
|
| +
|
| +void DragWindowResizer::Drag(const gfx::Point& location, int event_flags) {
|
| + bool destroyed = false;
|
| + destroyed_ = &destroyed;
|
| + window_resizer_->Drag(location, event_flags);
|
| + if (destroyed)
|
| + return;
|
| + last_mouse_location_ = location;
|
| +
|
| + // Show a phantom window for dragging in another root window.
|
| + if (HasSecondaryRootWindow()) {
|
| + gfx::Point location_in_screen = location;
|
| + wm::ConvertPointToScreen(GetTarget()->parent(), &location_in_screen);
|
| + const bool in_original_root =
|
| + wm::GetRootWindowAt(location_in_screen) == GetTarget()->GetRootWindow();
|
| + UpdateDragWindow(GetTarget()->bounds(), in_original_root);
|
| + } else {
|
| + drag_window_controller_.reset();
|
| + }
|
| +}
|
| +
|
| +void DragWindowResizer::CompleteDrag(int event_flags) {
|
| + window_resizer_->CompleteDrag(event_flags);
|
| +
|
| + GetTarget()->layer()->SetOpacity(details_.initial_opacity);
|
| + drag_window_controller_.reset();
|
| +
|
| + // Check if the destination is another display.
|
| + gfx::Point last_mouse_location_in_screen = last_mouse_location_;
|
| + wm::ConvertPointToScreen(GetTarget()->parent(),
|
| + &last_mouse_location_in_screen);
|
| + gfx::Screen* screen = Shell::GetScreen();
|
| + const gfx::Display dst_display =
|
| + screen->GetDisplayNearestPoint(last_mouse_location_in_screen);
|
| +
|
| + if (dst_display.id() !=
|
| + screen->GetDisplayNearestWindow(GetTarget()->GetRootWindow()).id()) {
|
| + const gfx::Rect dst_bounds =
|
| + ScreenAsh::ConvertRectToScreen(GetTarget()->parent(),
|
| + GetTarget()->bounds());
|
| + GetTarget()->SetBoundsInScreen(dst_bounds, dst_display);
|
| + }
|
| +}
|
| +
|
| +void DragWindowResizer::RevertDrag() {
|
| + window_resizer_->RevertDrag();
|
| +
|
| + drag_window_controller_.reset();
|
| + GetTarget()->layer()->SetOpacity(details_.initial_opacity);
|
| +}
|
| +
|
| +aura::Window* DragWindowResizer::GetTarget() {
|
| + return window_resizer_->GetTarget();
|
| +}
|
| +
|
| +void DragWindowResizer::UpdateDragWindow(const gfx::Rect& bounds,
|
| + bool in_original_root) {
|
| + if (details_.window_component != HTCAPTION || !ShouldAllowMouseWarp())
|
| + return;
|
| +
|
| + // It's available. Show a phantom window on the display if needed.
|
| + aura::RootWindow* another_root =
|
| + GetAnotherRootWindow(GetTarget()->GetRootWindow());
|
| + const gfx::Rect root_bounds_in_screen(another_root->GetBoundsInScreen());
|
| + const gfx::Rect bounds_in_screen =
|
| + ScreenAsh::ConvertRectToScreen(GetTarget()->parent(), bounds);
|
| + gfx::Rect bounds_in_another_root =
|
| + gfx::IntersectRects(root_bounds_in_screen, bounds_in_screen);
|
| + const float fraction_in_another_window =
|
| + (bounds_in_another_root.width() * bounds_in_another_root.height()) /
|
| + static_cast<float>(bounds.width() * bounds.height());
|
| +
|
| + if (fraction_in_another_window > 0) {
|
| + if (!drag_window_controller_.get()) {
|
| + drag_window_controller_.reset(
|
| + new DragWindowController(GetTarget()));
|
| + // Always show the drag phantom on the |another_root| window.
|
| + drag_window_controller_->SetDestinationDisplay(
|
| + Shell::GetScreen()->GetDisplayMatching(
|
| + another_root->GetBoundsInScreen()));
|
| + drag_window_controller_->Show();
|
| + } else {
|
| + // No animation.
|
| + drag_window_controller_->SetBounds(bounds_in_screen);
|
| + }
|
| + const float phantom_opacity =
|
| + !in_original_root ? 1 : (kMaxOpacity * fraction_in_another_window);
|
| + const float window_opacity =
|
| + in_original_root ? 1 : (kMaxOpacity * (1 - fraction_in_another_window));
|
| + drag_window_controller_->SetOpacity(phantom_opacity);
|
| + GetTarget()->layer()->SetOpacity(window_opacity);
|
| + } else {
|
| + drag_window_controller_.reset();
|
| + GetTarget()->layer()->SetOpacity(1.0f);
|
| + }
|
| +}
|
| +
|
| +bool DragWindowResizer::ShouldAllowMouseWarp() {
|
| + return (details_.window_component == HTCAPTION) &&
|
| + (GetTarget()->GetProperty(aura::client::kModalKey) ==
|
| + ui::MODAL_TYPE_NONE) &&
|
| + (GetTarget()->type() == aura::client::WINDOW_TYPE_NORMAL);
|
| +}
|
| +
|
| +} // namespace internal
|
| +} // namespace ash
|
|
|