1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ash/drag_drop/drag_image_view.h" 6 7 #include "skia/ext/image_operations.h" 8 #include "ui/aura/window.h" 9 #include "ui/compositor/dip_util.h" 10 #include "ui/gfx/canvas.h" 11 #include "ui/gfx/size_conversions.h" 12 #include "ui/views/corewm/shadow_types.h" 13 #include "ui/views/widget/widget.h" 14 15 namespace ash { 16 namespace internal { 17 18 namespace { 19 using views::Widget; 20 21 Widget* CreateDragWidget(gfx::NativeView context) { 22 Widget* drag_widget = new Widget; 23 Widget::InitParams params; 24 params.type = Widget::InitParams::TYPE_TOOLTIP; 25 params.keep_on_top = true; 26 params.context = context; 27 params.accept_events = false; 28 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 29 params.opacity = Widget::InitParams::TRANSLUCENT_WINDOW; 30 drag_widget->Init(params); 31 drag_widget->SetOpacity(0xFF); 32 drag_widget->GetNativeWindow()->set_owned_by_parent(false); 33 drag_widget->GetNativeWindow()->SetName("DragWidget"); 34 SetShadowType(drag_widget->GetNativeView(), views::corewm::SHADOW_TYPE_NONE); 35 return drag_widget; 36 } 37 } 38 39 DragImageView::DragImageView(gfx::NativeView context) : views::ImageView() { 40 widget_.reset(CreateDragWidget(context)); 41 widget_->SetContentsView(this); 42 widget_->SetAlwaysOnTop(true); 43 44 // We are owned by the DragDropController. 45 set_owned_by_client(); 46 } 47 48 DragImageView::~DragImageView() { 49 widget_->Hide(); 50 } 51 52 void DragImageView::SetBoundsInScreen(const gfx::Rect& bounds) { 53 widget_->SetBounds(bounds); 54 widget_size_ = bounds.size(); 55 } 56 57 void DragImageView::SetScreenPosition(const gfx::Point& position) { 58 widget_->SetBounds(gfx::Rect(position, widget_size_)); 59 } 60 61 void DragImageView::SetWidgetVisible(bool visible) { 62 if (visible != widget_->IsVisible()) { 63 if (visible) 64 widget_->Show(); 65 else 66 widget_->Hide(); 67 } 68 } 69 70 void DragImageView::OnPaint(gfx::Canvas* canvas) { 71 if (GetImage().isNull()) 72 return; 73 74 // |widget_size_| is in DIP. ImageSkia::size() also returns the size in DIP. 75 if (GetImage().size() == widget_size_) { 76 canvas->DrawImageInt(GetImage(), 0, 0); 77 } else { 78 float device_scale = 1; 79 if (widget_->GetNativeView() && widget_->GetNativeView()->layer()) { 80 device_scale = ui::GetDeviceScaleFactor( 81 widget_->GetNativeView()->layer()); 82 } 83 ui::ScaleFactor device_scale_factor = 84 ui::GetScaleFactorFromScale(device_scale); 85 86 // The drag image already has device scale factor applied. But 87 // |widget_size_| is in DIP units. 88 gfx::Size scaled_widget_size = gfx::ToRoundedSize( 89 gfx::ScaleSize(widget_size_, device_scale)); 90 gfx::ImageSkiaRep image_rep = GetImage().GetRepresentation( 91 device_scale_factor); 92 if (image_rep.is_null()) 93 return; 94 SkBitmap scaled = skia::ImageOperations::Resize( 95 image_rep.sk_bitmap(), skia::ImageOperations::RESIZE_LANCZOS3, 96 scaled_widget_size.width(), scaled_widget_size.height()); 97 gfx::ImageSkia image_skia(gfx::ImageSkiaRep(scaled, device_scale_factor)); 98 canvas->DrawImageInt(image_skia, 0, 0); 99 } 100 } 101 102 } // namespace internal 103 } // namespace ash 104