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/download/download_started_animation.h"
11 #include "base/message_loop/message_loop.h"
12 #include "content/public/browser/web_contents.h"
13 #include "content/public/browser/web_contents_view.h"
14 #include "grit/theme_resources.h"
15 #include "ui/base/resource/resource_bundle.h"
16 #include "ui/gfx/animation/linear_animation.h"
17 #include "ui/gfx/image/image.h"
18 #include "ui/gfx/rect.h"
22 // How long to spend moving downwards and fading out after waiting.
23 const int kMoveTimeMs
= 600;
25 // The animation framerate.
26 const int kFrameRateHz
= 60;
28 class DownloadStartedAnimationGtk
: public gfx::LinearAnimation
{
30 explicit DownloadStartedAnimationGtk(content::WebContents
* web_contents
);
32 // DownloadStartedAnimation will delete itself, but this is public so
33 // that we can use DeleteSoon().
34 virtual ~DownloadStartedAnimationGtk();
37 // Move the arrow to wherever it should currently be.
43 // Animation implementation.
44 virtual void AnimateToState(double state
) OVERRIDE
;
46 // The top level window that floats over the browser and displays the
50 // Dimensions of the image.
54 // The content area at the start of the animation. We store this so that the
55 // download shelf's resizing of the content area doesn't cause the animation
56 // to move around. This means that once started, the animation won't move
57 // with the parent window, but it's so fast that this shouldn't cause too
59 gfx::Rect web_contents_bounds_
;
61 DISALLOW_COPY_AND_ASSIGN(DownloadStartedAnimationGtk
);
64 DownloadStartedAnimationGtk::DownloadStartedAnimationGtk(
65 content::WebContents
* web_contents
)
66 : gfx::LinearAnimation(kMoveTimeMs
, kFrameRateHz
, NULL
),
68 static GdkPixbuf
* kDownloadImage
= NULL
;
69 if (!kDownloadImage
) {
70 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
71 kDownloadImage
= rb
.GetNativeImageNamed(
72 IDR_DOWNLOAD_ANIMATION_BEGIN
).ToGdkPixbuf();
75 width_
= gdk_pixbuf_get_width(kDownloadImage
);
76 height_
= gdk_pixbuf_get_height(kDownloadImage
);
78 // If we're too small to show the download image, then don't bother -
79 // the shelf will be enough.
80 web_contents
->GetView()->GetContainerBounds(&web_contents_bounds_
);
81 if (web_contents_bounds_
.height() < height_
)
84 // TODO(estade): don't show up on the wrong virtual desktop.
86 popup_
= gtk_window_new(GTK_WINDOW_POPUP
);
87 GtkWidget
* image
= gtk_image_new_from_pixbuf(kDownloadImage
);
88 gtk_container_add(GTK_CONTAINER(popup_
), image
);
90 // Set the shape of the window to that of the arrow. Areas with
91 // opacity less than 0xff (i.e. <100% opacity) will be transparent.
92 GdkBitmap
* mask
= gdk_pixmap_new(NULL
, width_
, height_
, 1);
93 gdk_pixbuf_render_threshold_alpha(kDownloadImage
, mask
,
97 gtk_widget_shape_combine_mask(popup_
, mask
, 0, 0);
101 gtk_widget_show_all(popup_
);
102 // Make sure our window has focus, is brought to the top, etc.
103 gtk_window_present(GTK_WINDOW(popup_
));
108 DownloadStartedAnimationGtk::~DownloadStartedAnimationGtk() {
111 void DownloadStartedAnimationGtk::Reposition() {
114 // Align the image with the bottom left of the web contents (so that it
115 // points to the newly created download).
116 gtk_window_move(GTK_WINDOW(popup_
),
117 web_contents_bounds_
.x(),
118 static_cast<int>(web_contents_bounds_
.bottom() -
119 height_
- height_
* (1 - GetCurrentValue())));
122 void DownloadStartedAnimationGtk::Close() {
125 gtk_widget_destroy(popup_
);
126 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, this);
129 void DownloadStartedAnimationGtk::AnimateToState(double state
) {
135 // Start at zero, peak halfway and end at zero.
136 double opacity
= std::min(1.0 - pow(GetCurrentValue() - 0.5, 2) * 4.0,
137 static_cast<double>(1.0));
139 // This only works when there's a compositing manager running. Oh well.
140 gtk_window_set_opacity(GTK_WINDOW(popup_
), opacity
);
147 void DownloadStartedAnimation::Show(content::WebContents
* web_contents
) {
148 // The animation will delete itself.
149 new DownloadStartedAnimationGtk(web_contents
);