• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 "chrome/browser/ui/views/tabs/dragged_tab_view.h"
6 
7 #include "base/stl_util-inl.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_skia.h"
11 #include "views/widget/widget.h"
12 
13 #if defined(OS_WIN)
14 #include "views/widget/widget_win.h"
15 #elif defined(OS_LINUX)
16 #include "views/widget/widget_gtk.h"
17 #endif
18 
19 static const int kTransparentAlpha = 200;
20 static const int kOpaqueAlpha = 255;
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);
25 
26 ////////////////////////////////////////////////////////////////////////////////
27 // DraggedTabView, public:
28 
DraggedTabView(const std::vector<views::View * > & renderers,const std::vector<gfx::Rect> & renderer_bounds,const gfx::Point & mouse_tab_offset,const gfx::Size & contents_size,NativeViewPhotobooth * photobooth)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_parent_owned(false);
41 
42   views::Widget::CreateParams params(views::Widget::CreateParams::TYPE_POPUP);
43   params.transparent = true;
44   params.keep_on_top = true;
45   params.delete_on_destroy = false;
46   container_.reset(views::Widget::CreateWidget(params));
47 #if defined(OS_WIN)
48   static_cast<views::WidgetWin*>(container_.get())->
49       set_can_update_layered_window(false);
50 
51   BOOL drag;
52   if ((::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &drag, 0) != 0) &&
53       (drag == FALSE)) {
54     show_contents_on_drag_ = false;
55   }
56 #endif
57   gfx::Size container_size(PreferredContainerSize());
58   container_->Init(NULL, gfx::Rect(gfx::Point(), container_size));
59   container_->SetContentsView(this);
60   container_->SetOpacity(kTransparentAlpha);
61   container_->SetBounds(gfx::Rect(gfx::Point(), container_size));
62 }
63 
~DraggedTabView()64 DraggedTabView::~DraggedTabView() {
65   parent()->RemoveChildView(this);
66   container_->CloseNow();
67   STLDeleteElements(&renderers_);
68 }
69 
MoveTo(const gfx::Point & screen_point)70 void DraggedTabView::MoveTo(const gfx::Point& screen_point) {
71   int x;
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());
78   } else {
79     x = screen_point.x() - ScaleValue(mouse_tab_offset_.x());
80   }
81   int y = screen_point.y() - ScaleValue(mouse_tab_offset_.y());
82 
83 #if defined(OS_WIN)
84   // TODO(beng): make this cross-platform
85   int show_flags = container_->IsVisible() ? SWP_NOZORDER : SWP_SHOWWINDOW;
86   SetWindowPos(container_->GetNativeView(), HWND_TOP, x, y, 0, 0,
87                SWP_NOSIZE | SWP_NOACTIVATE | show_flags);
88 #else
89   gfx::Rect bounds = container_->GetWindowScreenBounds();
90   container_->SetBounds(gfx::Rect(x, y, bounds.width(), bounds.height()));
91   if (!container_->IsVisible())
92     container_->Show();
93 #endif
94 }
95 
Update()96 void DraggedTabView::Update() {
97   SchedulePaint();
98 }
99 
100 ///////////////////////////////////////////////////////////////////////////////
101 // DraggedTabView, views::View overrides:
102 
OnPaint(gfx::Canvas * canvas)103 void DraggedTabView::OnPaint(gfx::Canvas* canvas) {
104   if (show_contents_on_drag_)
105     PaintDetachedView(canvas);
106   else
107     PaintFocusRect(canvas);
108 }
109 
Layout()110 void DraggedTabView::Layout() {
111   int max_width = GetPreferredSize().width();
112   for (size_t i = 0; i < renderers_.size(); ++i) {
113     gfx::Rect bounds = renderer_bounds_[i];
114     bounds.set_y(0);
115     if (base::i18n::IsRTL())
116       bounds.set_x(max_width - bounds.x() - bounds.width());
117     renderers_[i]->SetBoundsRect(bounds);
118   }
119 }
120 
GetPreferredSize()121 gfx::Size DraggedTabView::GetPreferredSize() {
122   DCHECK(!renderer_bounds_.empty());
123   int max_renderer_x = renderer_bounds_.back().right();
124   int width = std::max(max_renderer_x, contents_size_.width()) +
125       kTwiceDragFrameBorderSize;
126   int height = renderer_bounds_.back().height() + kDragFrameBorderSize +
127       contents_size_.height();
128   return gfx::Size(width, height);
129 }
130 
131 ////////////////////////////////////////////////////////////////////////////////
132 // DraggedTabView, private:
133 
PaintDetachedView(gfx::Canvas * canvas)134 void DraggedTabView::PaintDetachedView(gfx::Canvas* canvas) {
135   gfx::Size ps = GetPreferredSize();
136   gfx::CanvasSkia scale_canvas(ps.width(), ps.height(), false);
137   SkBitmap& bitmap_device = const_cast<SkBitmap&>(
138       scale_canvas.getTopPlatformDevice().accessBitmap(true));
139   bitmap_device.eraseARGB(0, 0, 0, 0);
140 
141   int tab_height = renderer_bounds_.back().height();
142   scale_canvas.FillRectInt(kDraggedTabBorderColor, 0,
143       tab_height - kDragFrameBorderSize,
144       ps.width(), ps.height() - tab_height);
145   int image_x = kDragFrameBorderSize;
146   int image_y = tab_height;
147   int image_w = ps.width() - kTwiceDragFrameBorderSize;
148   int image_h = contents_size_.height();
149   scale_canvas.FillRectInt(SK_ColorBLACK, image_x, image_y, image_w, image_h);
150   photobooth_->PaintScreenshotIntoCanvas(
151       &scale_canvas,
152       gfx::Rect(image_x, image_y, image_w, image_h));
153   for (size_t i = 0; i < renderers_.size(); ++i)
154     renderers_[i]->Paint(&scale_canvas);
155 
156   SkIRect subset;
157   subset.set(0, 0, ps.width(), ps.height());
158   SkBitmap mipmap = scale_canvas.ExtractBitmap();
159   mipmap.buildMipMap(true);
160 
161   SkShader* bitmap_shader =
162       SkShader::CreateBitmapShader(mipmap, SkShader::kClamp_TileMode,
163                                    SkShader::kClamp_TileMode);
164 
165   SkMatrix shader_scale;
166   shader_scale.setScale(kScalingFactor, kScalingFactor);
167   bitmap_shader->setLocalMatrix(shader_scale);
168 
169   SkPaint paint;
170   paint.setShader(bitmap_shader);
171   paint.setAntiAlias(true);
172   bitmap_shader->unref();
173 
174   SkRect rc;
175   rc.fLeft = 0;
176   rc.fTop = 0;
177   rc.fRight = SkIntToScalar(ps.width());
178   rc.fBottom = SkIntToScalar(ps.height());
179   canvas->AsCanvasSkia()->drawRect(rc, paint);
180 }
181 
PaintFocusRect(gfx::Canvas * canvas)182 void DraggedTabView::PaintFocusRect(gfx::Canvas* canvas) {
183   gfx::Size ps = GetPreferredSize();
184   canvas->DrawFocusRect(0, 0,
185                         static_cast<int>(ps.width() * kScalingFactor),
186                         static_cast<int>(ps.height() * kScalingFactor));
187 }
188 
PreferredContainerSize()189 gfx::Size DraggedTabView::PreferredContainerSize() {
190   gfx::Size ps = GetPreferredSize();
191   return gfx::Size(ScaleValue(ps.width()), ScaleValue(ps.height()));
192 }
193 
ScaleValue(int value)194 int DraggedTabView::ScaleValue(int value) {
195   return static_cast<int>(value * kScalingFactor);
196 }
197