12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/wm/drag_window_controller.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/shell_window_ids.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/wm/window_util.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/client/screen_position_client.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/window.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/compositor/layer.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/compositor/layer_tree_owner.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/compositor/scoped_layer_animation_settings.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/view.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/widget/widget.h"
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/shadow_types.h"
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/window_util.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace ash {
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DragWindowController::DragWindowController(aura::Window* window)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : window_(window),
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      drag_widget_(NULL) {
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DragWindowController::~DragWindowController() {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Hide();
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DragWindowController::SetDestinationDisplay(
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Display& dst_display) {
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dst_display_ = dst_display;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DragWindowController::Show() {
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!drag_widget_)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CreateDragWidget(window_->GetBoundsInScreen());
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_widget_->Show();
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DragWindowController::SetBounds(const gfx::Rect& bounds) {
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(drag_widget_);
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bounds_ = bounds;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetBoundsInternal(bounds);
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DragWindowController::Hide() {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (drag_widget_) {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    drag_widget_->Close();
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    drag_widget_ = NULL;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  layer_owner_.reset();
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DragWindowController::SetOpacity(float opacity) {
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(drag_widget_);
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::Layer* layer = drag_widget_->GetNativeWindow()->layer();
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::ScopedLayerAnimationSettings scoped_setter(layer->GetAnimator());
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  layer->SetOpacity(opacity);
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DragWindowController::CreateDragWidget(const gfx::Rect& bounds) {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!drag_widget_);
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_widget_ = new views::Widget;
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.parent = window_->parent();
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.keep_on_top = true;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_widget_->set_focus_on_creation(false);
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_widget_->Init(params);
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_widget_->SetVisibilityChangedAnimationsEnabled(false);
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_widget_->GetNativeWindow()->SetName("DragWindow");
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_widget_->GetNativeWindow()->set_id(kShellWindowId_PhantomWindow);
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Show shadow for the dragging window.
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetShadowType(drag_widget_->GetNativeWindow(),
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                ::wm::SHADOW_TYPE_RECTANGULAR);
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetBoundsInternal(bounds);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_widget_->StackAbove(window_);
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RecreateWindowLayers();
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::Window* window = drag_widget_->GetNativeWindow();
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  layer_owner_->root()->SetVisible(true);
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window->layer()->Add(layer_owner_->root());
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window->layer()->StackAtTop(layer_owner_->root());
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Show the widget after all the setups.
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  drag_widget_->Show();
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Fade the window in.
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::Layer* widget_layer = drag_widget_->GetNativeWindow()->layer();
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  widget_layer->SetOpacity(0);
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::ScopedLayerAnimationSettings scoped_setter(widget_layer->GetAnimator());
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  widget_layer->SetOpacity(1);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DragWindowController::SetBoundsInternal(const gfx::Rect& bounds) {
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::Window* window = drag_widget_->GetNativeWindow();
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::client::ScreenPositionClient* screen_position_client =
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      aura::client::GetScreenPositionClient(window->GetRootWindow());
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (screen_position_client && dst_display_.is_valid())
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    screen_position_client->SetBounds(window, bounds, dst_display_);
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    drag_widget_->SetBounds(bounds);
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DragWindowController::RecreateWindowLayers() {
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(!layer_owner_.get());
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  layer_owner_ = ::wm::RecreateLayers(window_);
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  layer_owner_->root()->set_delegate(window_->layer()->delegate());
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Place the layer at (0, 0) of the DragWindowController's window.
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Rect layer_bounds = layer_owner_->root()->bounds();
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  layer_bounds.set_origin(gfx::Point(0, 0));
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  layer_owner_->root()->SetBounds(layer_bounds);
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  layer_owner_->root()->SetVisible(false);
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Detach it from the current container.
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  layer_owner_->root()->parent()->Remove(layer_owner_->root());
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace ash
121