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.
5 #include "chrome/browser/ui/views/tabs/dragged_tab_view.h"
7 #include "base/stl_util.h"
8 #include "chrome/browser/ui/views/tabs/native_view_photobooth.h"
9 #include "third_party/skia/include/core/SkShader.h"
10 #include "ui/gfx/canvas.h"
11 #include "ui/views/widget/widget.h"
14 #include "ui/views/widget/native_widget_aura.h"
16 #include "ui/gfx/win/dpi.h"
17 #include "ui/views/widget/native_widget_win.h"
20 static const int kTransparentAlpha
= 200;
21 static const int kDragFrameBorderSize
= 2;
22 static const int kTwiceDragFrameBorderSize
= 2 * kDragFrameBorderSize
;
23 static const float kScalingFactor
= 0.5;
24 static const SkColor kDraggedTabBorderColor
= SkColorSetRGB(103, 129, 162);
26 ////////////////////////////////////////////////////////////////////////////////
27 // DraggedTabView, public:
29 DraggedTabView::DraggedTabView(const std::vector
<views::View
*>& renderers
,
30 const std::vector
<gfx::Rect
>& renderer_bounds
,
31 const gfx::Point
& mouse_tab_offset
,
32 const gfx::Size
& contents_size
,
33 NativeViewPhotobooth
* photobooth
)
34 : renderers_(renderers
),
35 renderer_bounds_(renderer_bounds
),
36 show_contents_on_drag_(true),
37 mouse_tab_offset_(mouse_tab_offset
),
38 photobooth_(photobooth
),
39 contents_size_(contents_size
) {
40 set_owned_by_client();
42 container_
.reset(new views::Widget
);
43 views::Widget::InitParams
params(views::Widget::InitParams::TYPE_POPUP
);
44 params
.opacity
= views::Widget::InitParams::TRANSLUCENT_WINDOW
;
45 params
.keep_on_top
= true;
46 params
.ownership
= views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
47 params
.bounds
= gfx::Rect(PreferredContainerSize());
48 container_
->Init(params
);
49 container_
->SetContentsView(this);
50 #if defined(OS_WIN) && !defined(USE_AURA)
51 static_cast<views::NativeWidgetWin
*>(container_
->native_widget())->
52 SetCanUpdateLayeredWindow(false);
55 if ((::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS
, 0, &drag
, 0) != 0) &&
57 show_contents_on_drag_
= false;
60 container_
->SetOpacity(kTransparentAlpha
);
61 container_
->SetBounds(gfx::Rect(params
.bounds
.size()));
64 DraggedTabView::~DraggedTabView() {
65 parent()->RemoveChildView(this);
66 container_
->CloseNow();
67 STLDeleteElements(&renderers_
);
70 void DraggedTabView::MoveTo(const gfx::Point
& screen_point
) {
72 if (base::i18n::IsRTL()) {
73 // On RTL locales, a dragged tab (when it is not attached to a tab strip)
74 // is rendered using a right-to-left orientation so we should calculate the
75 // window position differently.
76 gfx::Size ps
= GetPreferredSize();
77 x
= screen_point
.x() + ScaleValue(mouse_tab_offset_
.x() - ps
.width());
79 x
= screen_point
.x() - ScaleValue(mouse_tab_offset_
.x());
81 int y
= screen_point
.y() - ScaleValue(mouse_tab_offset_
.y());
83 gfx::Rect bounds
= container_
->GetWindowBoundsInScreen();
84 container_
->SetBounds(gfx::Rect(x
, y
, bounds
.width(), bounds
.height()));
85 if (!container_
->IsVisible())
89 void DraggedTabView::Update() {
93 ///////////////////////////////////////////////////////////////////////////////
94 // DraggedTabView, views::View overrides:
96 void DraggedTabView::OnPaint(gfx::Canvas
* canvas
) {
97 if (show_contents_on_drag_
)
98 PaintDetachedView(canvas
);
100 PaintFocusRect(canvas
);
103 void DraggedTabView::Layout() {
104 int max_width
= GetPreferredSize().width();
105 for (size_t i
= 0; i
< renderers_
.size(); ++i
) {
106 gfx::Rect bounds
= renderer_bounds_
[i
];
108 if (base::i18n::IsRTL())
109 bounds
.set_x(max_width
- bounds
.x() - bounds
.width());
110 renderers_
[i
]->SetBoundsRect(bounds
);
114 gfx::Size
DraggedTabView::GetPreferredSize() {
115 DCHECK(!renderer_bounds_
.empty());
116 int max_renderer_x
= renderer_bounds_
.back().right();
117 int width
= std::max(max_renderer_x
, contents_size_
.width()) +
118 kTwiceDragFrameBorderSize
;
119 int height
= renderer_bounds_
.back().height() + kDragFrameBorderSize
+
120 contents_size_
.height();
121 return gfx::Size(width
, height
);
124 ////////////////////////////////////////////////////////////////////////////////
125 // DraggedTabView, private:
127 void DraggedTabView::PaintDetachedView(gfx::Canvas
* canvas
) {
128 gfx::Size ps
= GetPreferredSize();
129 // TODO(pkotwicz): DIP enable this class.
130 gfx::Canvas
scale_canvas(ps
, 1.0f
, false);
131 SkBitmap
& bitmap_device
= const_cast<SkBitmap
&>(
132 skia::GetTopDevice(*scale_canvas
.sk_canvas())->accessBitmap(true));
133 bitmap_device
.eraseARGB(0, 0, 0, 0);
135 int tab_height
= renderer_bounds_
.back().height();
136 scale_canvas
.FillRect(gfx::Rect(0, tab_height
- kDragFrameBorderSize
,
137 ps
.width(), ps
.height() - tab_height
),
138 kDraggedTabBorderColor
);
139 gfx::Rect
image_rect(kDragFrameBorderSize
,
141 ps
.width() - kTwiceDragFrameBorderSize
,
142 contents_size_
.height());
143 scale_canvas
.FillRect(image_rect
, SK_ColorBLACK
);
144 photobooth_
->PaintScreenshotIntoCanvas(&scale_canvas
, image_rect
);
145 for (size_t i
= 0; i
< renderers_
.size(); ++i
)
146 renderers_
[i
]->Paint(&scale_canvas
);
148 SkBitmap mipmap
= scale_canvas
.ExtractImageRep().sk_bitmap();
149 mipmap
.buildMipMap(true);
151 skia::RefPtr
<SkShader
> bitmap_shader
= skia::AdoptRef(
152 SkShader::CreateBitmapShader(mipmap
, SkShader::kClamp_TileMode
,
153 SkShader::kClamp_TileMode
));
155 SkMatrix shader_scale
;
156 shader_scale
.setScale(kScalingFactor
, kScalingFactor
);
157 bitmap_shader
->setLocalMatrix(shader_scale
);
160 paint
.setShader(bitmap_shader
.get());
161 paint
.setAntiAlias(true);
163 canvas
->DrawRect(gfx::Rect(ps
), paint
);
166 void DraggedTabView::PaintFocusRect(gfx::Canvas
* canvas
) {
167 gfx::Size ps
= GetPreferredSize();
168 canvas
->DrawFocusRect(
170 static_cast<int>(ps
.width() * kScalingFactor
),
171 static_cast<int>(ps
.height() * kScalingFactor
)));
174 gfx::Size
DraggedTabView::PreferredContainerSize() {
175 gfx::Size ps
= GetPreferredSize();
176 return gfx::Size(ScaleValue(ps
.width()), ScaleValue(ps
.height()));
179 int DraggedTabView::ScaleValue(int value
) {
180 return static_cast<int>(value
* kScalingFactor
);