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/drag_drop/drag_image_view.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "skia/ext/image_operations.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h" 94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/compositor/dip_util.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/canvas.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/size_conversions.h" 1303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "ui/resources/grit/ui_resources.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h" 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/shadow_types.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using views::Widget; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Widget* CreateDragWidget(gfx::NativeView context) { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Widget* drag_widget = new Widget; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Widget::InitParams params; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.type = Widget::InitParams::TYPE_TOOLTIP; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.keep_on_top = true; 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) params.context = context; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.accept_events = false; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch params.opacity = Widget::InitParams::TRANSLUCENT_WINDOW; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_widget->Init(params); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_widget->SetOpacity(0xFF); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_widget->GetNativeWindow()->set_owned_by_parent(false); 337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch drag_widget->GetNativeWindow()->SetName("DragWidget"); 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SetShadowType(drag_widget->GetNativeView(), wm::SHADOW_TYPE_NONE); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return drag_widget; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)DragImageView::DragImageView(gfx::NativeView context, 404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ui::DragDropTypes::DragEventSource event_source) 414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : views::ImageView(), 424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) drag_event_source_(event_source), 434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) touch_drag_operation_(ui::DragDropTypes::DRAG_NONE) { 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) widget_.reset(CreateDragWidget(context)); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) widget_->SetContentsView(this); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) widget_->SetAlwaysOnTop(true); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We are owned by the DragDropController. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_owned_by_client(); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DragImageView::~DragImageView() { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) widget_->Hide(); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DragImageView::SetBoundsInScreen(const gfx::Rect& bounds) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) widget_->SetBounds(bounds); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) widget_size_ = bounds.size(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DragImageView::SetScreenPosition(const gfx::Point& position) { 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) widget_->SetBounds(gfx::Rect(position, widget_size_)); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 65424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)gfx::Rect DragImageView::GetBoundsInScreen() const { 66424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return widget_->GetWindowBoundsInScreen(); 67424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 68424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DragImageView::SetWidgetVisible(bool visible) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visible != widget_->IsVisible()) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (visible) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) widget_->Show(); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) widget_->Hide(); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void DragImageView::SetTouchDragOperationHintOff() { 794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Simply set the drag type to non-touch so that no hint is drawn. 804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) drag_event_source_ = ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE; 814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SchedulePaint(); 824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void DragImageView::SetTouchDragOperation(int operation) { 854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (touch_drag_operation_ == operation) 864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) touch_drag_operation_ = operation; 884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SchedulePaint(); 894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void DragImageView::SetTouchDragOperationHintPosition( 924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const gfx::Point& position) { 934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (touch_drag_operation_indicator_position_ == position) 944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) touch_drag_operation_indicator_position_ = position; 964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SchedulePaint(); 974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 99424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void DragImageView::SetOpacity(float visibility) { 100424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK_GE(visibility, 0.0f); 101424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK_LE(visibility, 1.0f); 102424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) widget_->SetOpacity(static_cast<int>(0xff * visibility)); 103424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 104424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DragImageView::OnPaint(gfx::Canvas* canvas) { 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (GetImage().isNull()) 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |widget_size_| is in DIP. ImageSkia::size() also returns the size in DIP. 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (GetImage().size() == widget_size_) { 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) canvas->DrawImageInt(GetImage(), 0, 0); 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) float device_scale = 1; 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (widget_->GetNativeView() && widget_->GetNativeView()->layer()) { 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) device_scale = ui::GetDeviceScaleFactor( 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) widget_->GetNativeView()->layer()); 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The drag image already has device scale factor applied. But 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |widget_size_| is in DIP units. 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Size scaled_widget_size = gfx::ToRoundedSize( 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::ScaleSize(widget_size_, device_scale)); 12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::ImageSkiaRep image_rep = GetImage().GetRepresentation(device_scale); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (image_rep.is_null()) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkBitmap scaled = skia::ImageOperations::Resize( 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) image_rep.sk_bitmap(), skia::ImageOperations::RESIZE_LANCZOS3, 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scaled_widget_size.width(), scaled_widget_size.height()); 12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::ImageSkia image_skia(gfx::ImageSkiaRep(scaled, device_scale)); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) canvas->DrawImageInt(image_skia, 0, 0); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (drag_event_source_ != ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH) 1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Select appropriate drag hint. 1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) gfx::Image* drag_hint = 1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &ui::ResourceBundle::GetSharedInstance().GetImageNamed( 1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) IDR_TOUCH_DRAG_TIP_NODROP); 1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (touch_drag_operation_ & ui::DragDropTypes::DRAG_COPY) { 1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) drag_hint = &ui::ResourceBundle::GetSharedInstance().GetImageNamed( 1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) IDR_TOUCH_DRAG_TIP_COPY); 1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else if (touch_drag_operation_ & ui::DragDropTypes::DRAG_MOVE) { 1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) drag_hint = &ui::ResourceBundle::GetSharedInstance().GetImageNamed( 1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) IDR_TOUCH_DRAG_TIP_MOVE); 1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else if (touch_drag_operation_ & ui::DragDropTypes::DRAG_LINK) { 1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) drag_hint = &ui::ResourceBundle::GetSharedInstance().GetImageNamed( 1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) IDR_TOUCH_DRAG_TIP_LINK); 1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!drag_hint->IsEmpty()) { 1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) gfx::Size drag_hint_size = drag_hint->Size(); 1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Enlarge widget if required to fit the drag hint image. 1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (drag_hint_size.width() > widget_size_.width() || 1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) drag_hint_size.height() > widget_size_.height()) { 1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) gfx::Size new_widget_size = widget_size_; 1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) new_widget_size.SetToMax(drag_hint_size); 1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) widget_->SetSize(new_widget_size); 1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Make sure drag hint image is positioned within the widget. 1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) gfx::Point drag_hint_position = touch_drag_operation_indicator_position_; 1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) drag_hint_position.Offset(-drag_hint_size.width() / 2, 0); 1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) gfx::Rect drag_hint_bounds(drag_hint_position, drag_hint_size); 1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) drag_hint_bounds.AdjustToFit(gfx::Rect(widget_size_)); 1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Draw image. 1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) canvas->DrawImageInt(*(drag_hint->ToImageSkia()), 1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) drag_hint_bounds.x(), drag_hint_bounds.y()); 1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace ash 173