This source file includes following definitions.
- GetDockedLayoutManagerAtPoint
- Create
- Drag
- CompleteDrag
- RevertDrag
- weak_ptr_factory_
- MaybeSnapToEdge
- StartedDragging
- FinishedDragging
- MaybeReparentWindowOnDragCompletion
#include "ash/wm/dock/docked_window_resizer.h"
#include "ash/display/display_controller.h"
#include "ash/root_window_controller.h"
#include "ash/screen_util.h"
#include "ash/shelf/shelf.h"
#include "ash/shelf/shelf_types.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/wm/coordinate_conversion.h"
#include "ash/wm/dock/docked_window_layout_manager.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "ash/wm/workspace/magnetism_matcher.h"
#include "ash/wm/workspace/workspace_window_resizer.h"
#include "base/command_line.h"
#include "base/memory/weak_ptr.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/window_tree_client.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/hit_test.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/screen.h"
#include "ui/views/widget/widget.h"
namespace ash {
namespace {
DockedWindowLayoutManager* GetDockedLayoutManagerAtPoint(
const gfx::Point& point) {
gfx::Display display = ScreenUtil::FindDisplayContainingPoint(point);
if (!display.is_valid())
return NULL;
aura::Window* root = Shell::GetInstance()->display_controller()->
GetRootWindowForDisplayId(display.id());
aura::Window* dock_container = Shell::GetContainer(
root, kShellWindowId_DockedContainer);
return static_cast<DockedWindowLayoutManager*>(
dock_container->layout_manager());
}
}
DockedWindowResizer::~DockedWindowResizer() {
}
DockedWindowResizer*
DockedWindowResizer::Create(WindowResizer* next_window_resizer,
wm::WindowState* window_state) {
return new DockedWindowResizer(next_window_resizer, window_state);
}
void DockedWindowResizer::Drag(const gfx::Point& location, int event_flags) {
last_location_ = location;
wm::ConvertPointToScreen(GetTarget()->parent(), &last_location_);
if (!did_move_or_resize_) {
did_move_or_resize_ = true;
StartedDragging();
}
gfx::Point offset;
gfx::Rect bounds(CalculateBoundsForDrag(location));
MaybeSnapToEdge(bounds, &offset);
gfx::Point modified_location(location);
modified_location.Offset(offset.x(), offset.y());
base::WeakPtr<DockedWindowResizer> resizer(weak_ptr_factory_.GetWeakPtr());
next_window_resizer_->Drag(modified_location, event_flags);
if (!resizer)
return;
DockedWindowLayoutManager* new_dock_layout =
GetDockedLayoutManagerAtPoint(last_location_);
if (new_dock_layout && new_dock_layout != dock_layout_) {
if (is_docked_ && dock_layout_->is_dragged_window_docked())
dock_layout_->UndockDraggedWindow();
if (dock_layout_ != initial_dock_layout_)
dock_layout_->FinishDragging(
DOCKED_ACTION_NONE,
details().source == aura::client::WINDOW_MOVE_SOURCE_MOUSE ?
DOCKED_ACTION_SOURCE_MOUSE : DOCKED_ACTION_SOURCE_TOUCH);
is_docked_ = false;
dock_layout_ = new_dock_layout;
if (new_dock_layout != initial_dock_layout_)
new_dock_layout->StartDragging(GetTarget());
}
is_docked_ = dock_layout_->is_dragged_window_docked();
if (!is_docked_)
was_bounds_changed_by_user_ = false;
}
void DockedWindowResizer::CompleteDrag() {
next_window_resizer_->CompleteDrag();
FinishedDragging(aura::client::MOVE_SUCCESSFUL);
}
void DockedWindowResizer::RevertDrag() {
next_window_resizer_->RevertDrag();
if (is_docked_ != was_docked_) {
is_docked_ = was_docked_;
if (is_docked_)
dock_layout_->DockDraggedWindow(GetTarget());
else
dock_layout_->UndockDraggedWindow();
}
FinishedDragging(aura::client::MOVE_CANCELED);
}
DockedWindowResizer::DockedWindowResizer(WindowResizer* next_window_resizer,
wm::WindowState* window_state)
: WindowResizer(window_state),
next_window_resizer_(next_window_resizer),
dock_layout_(NULL),
initial_dock_layout_(NULL),
did_move_or_resize_(false),
was_docked_(false),
is_docked_(false),
was_bounds_changed_by_user_(window_state->bounds_changed_by_user()),
weak_ptr_factory_(this) {
DCHECK(details().is_resizable);
aura::Window* dock_container = Shell::GetContainer(
GetTarget()->GetRootWindow(),
kShellWindowId_DockedContainer);
dock_layout_ = static_cast<DockedWindowLayoutManager*>(
dock_container->layout_manager());
initial_dock_layout_ = dock_layout_;
was_docked_ = GetTarget()->parent() == dock_container;
is_docked_ = was_docked_;
}
void DockedWindowResizer::MaybeSnapToEdge(const gfx::Rect& bounds,
gfx::Point* offset) {
if (!was_docked_)
return;
DockedAlignment dock_alignment = dock_layout_->CalculateAlignment();
gfx::Rect dock_bounds = ScreenUtil::ConvertRectFromScreen(
GetTarget()->parent(),
dock_layout_->dock_container()->GetBoundsInScreen());
const int kSnapToDockDistance = MagnetismMatcher::kMagneticDistance;
if (dock_alignment == DOCKED_ALIGNMENT_LEFT ||
dock_alignment == DOCKED_ALIGNMENT_NONE) {
const int distance = bounds.x() - dock_bounds.x();
if (distance < kSnapToDockDistance && distance > 0) {
offset->set_x(-distance);
return;
}
}
if (dock_alignment == DOCKED_ALIGNMENT_RIGHT ||
dock_alignment == DOCKED_ALIGNMENT_NONE) {
const int distance = dock_bounds.right() - bounds.right();
if (distance < kSnapToDockDistance && distance > 0)
offset->set_x(distance);
}
}
void DockedWindowResizer::StartedDragging() {
if (is_docked_ &&
(details().bounds_change & WindowResizer::kBoundsChange_Resizes)) {
window_state_->set_bounds_changed_by_user(true);
}
dock_layout_->StartDragging(GetTarget());
if (GetTarget()->type() != ui::wm::WINDOW_TYPE_PANEL &&
GetTarget()->parent()->id() == kShellWindowId_DefaultContainer) {
aura::Window* docked_container = Shell::GetContainer(
GetTarget()->GetRootWindow(),
kShellWindowId_DockedContainer);
wm::ReparentChildWithTransientChildren(GetTarget(),
GetTarget()->parent(),
docked_container);
}
if (is_docked_)
dock_layout_->DockDraggedWindow(GetTarget());
}
void DockedWindowResizer::FinishedDragging(
aura::client::WindowMoveResult move_result) {
if (!did_move_or_resize_)
return;
did_move_or_resize_ = false;
aura::Window* window = GetTarget();
const bool is_attached_panel = window->type() == ui::wm::WINDOW_TYPE_PANEL &&
window_state_->panel_attached();
const bool is_resized =
(details().bounds_change & WindowResizer::kBoundsChange_Resizes) != 0;
if (!window_state_->IsMinimized() && !window_state_->IsNormalStateType())
is_docked_ = false;
if (!is_attached_panel && is_docked_ && !is_resized) {
gfx::Rect bounds = ScreenUtil::ConvertRectFromScreen(
window->parent(), dock_layout_->dragged_bounds());
if (!bounds.IsEmpty() && bounds.width() != window->bounds().width()) {
window->SetBounds(bounds);
}
}
if (is_resized && is_docked_ && window_state_->HasRestoreBounds()) {
gfx::Rect restore_bounds = window->GetBoundsInScreen();
restore_bounds.set_height(
window_state_->GetRestoreBoundsInScreen().height());
window_state_->SetRestoreBoundsInScreen(restore_bounds);
}
DockedAction action = MaybeReparentWindowOnDragCompletion(is_resized,
is_attached_panel);
dock_layout_->FinishDragging(
move_result == aura::client::MOVE_CANCELED ? DOCKED_ACTION_NONE : action,
details().source == aura::client::WINDOW_MOVE_SOURCE_MOUSE ?
DOCKED_ACTION_SOURCE_MOUSE : DOCKED_ACTION_SOURCE_TOUCH);
if (initial_dock_layout_ != dock_layout_)
initial_dock_layout_->FinishDragging(
DOCKED_ACTION_NONE,
details().source == aura::client::WINDOW_MOVE_SOURCE_MOUSE ?
DOCKED_ACTION_SOURCE_MOUSE : DOCKED_ACTION_SOURCE_TOUCH);
is_docked_ = false;
}
DockedAction DockedWindowResizer::MaybeReparentWindowOnDragCompletion(
bool is_resized, bool is_attached_panel) {
aura::Window* window = GetTarget();
DockedAction action = DOCKED_ACTION_NONE;
aura::Window* dock_container = Shell::GetContainer(
window->GetRootWindow(),
kShellWindowId_DockedContainer);
if ((is_resized || !is_attached_panel) &&
is_docked_ != (window->parent() == dock_container)) {
if (is_docked_) {
wm::ReparentChildWithTransientChildren(window,
window->parent(),
dock_container);
action = DOCKED_ACTION_DOCK;
} else if (window->parent()->id() == kShellWindowId_DockedContainer) {
gfx::Rect near_last_location(last_location_, gfx::Size());
aura::Window* previous_parent = window->parent();
aura::client::ParentWindowWithContext(window, window, near_last_location);
if (window->parent() != previous_parent) {
wm::ReparentTransientChildrenOfChild(window,
previous_parent,
window->parent());
}
action = was_docked_ ? DOCKED_ACTION_UNDOCK : DOCKED_ACTION_NONE;
}
} else {
if (is_resized && is_docked_ && was_docked_)
action = DOCKED_ACTION_RESIZE;
else if (is_docked_ && was_docked_)
action = DOCKED_ACTION_REORDER;
else if (is_docked_ && !was_docked_)
action = DOCKED_ACTION_DOCK;
else
action = DOCKED_ACTION_NONE;
}
if (is_docked_) {
wm::GetWindowState(window)->set_bounds_changed_by_user(
was_docked_ && (is_resized || was_bounds_changed_by_user_));
}
return action;
}
}