OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 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/gtk/tabs/dragged_tab_gtk.h" |
| 6 |
| 7 #include <gdk/gdk.h> |
| 8 |
| 9 #include "app/gfx/canvas.h" |
| 10 #include "chrome/browser/tab_contents/tab_contents.h" |
| 11 #include "chrome/browser/tabs/tab_strip_model.h" |
| 12 #include "chrome/browser/gtk/tabs/tab_renderer_gtk.h" |
| 13 #include "third_party/skia/include/core/SkShader.h" |
| 14 |
| 15 namespace { |
| 16 |
| 17 // The size of the dragged window frame. |
| 18 const int kDragFrameBorderSize = 2; |
| 19 const int kTwiceDragFrameBorderSize = 2 * kDragFrameBorderSize; |
| 20 |
| 21 // Used to scale the dragged window sizes. |
| 22 const float kScalingFactor = 0.5; |
| 23 |
| 24 const int kAnimateToBoundsDurationMs = 150; |
| 25 |
| 26 } // namespace |
| 27 |
| 28 //////////////////////////////////////////////////////////////////////////////// |
| 29 // DraggedTabGtk, public: |
| 30 |
| 31 DraggedTabGtk::DraggedTabGtk(TabContents* datasource, |
| 32 const gfx::Point& mouse_tab_offset, |
| 33 const gfx::Size& contents_size) |
| 34 : renderer_(new TabRendererGtk), |
| 35 attached_(false), |
| 36 mouse_tab_offset_(mouse_tab_offset), |
| 37 attached_tab_size_(TabRendererGtk::GetMinimumSelectedSize()), |
| 38 contents_size_(contents_size), |
| 39 close_animation_(this) { |
| 40 renderer_->UpdateData(datasource, false); |
| 41 |
| 42 container_.Own(gtk_window_new(GTK_WINDOW_POPUP)); |
| 43 SetContainerColorMap(); |
| 44 gtk_widget_set_app_paintable(container_.get(), TRUE); |
| 45 g_signal_connect(G_OBJECT(container_.get()), "expose-event", |
| 46 G_CALLBACK(OnExpose), this); |
| 47 gtk_container_add(GTK_CONTAINER(container_.get()), renderer_->widget()); |
| 48 gtk_widget_show_all(container_.get()); |
| 49 } |
| 50 |
| 51 DraggedTabGtk::~DraggedTabGtk() { |
| 52 gtk_widget_destroy(container_.get()); |
| 53 } |
| 54 |
| 55 void DraggedTabGtk::MoveTo(const gfx::Point& screen_point) { |
| 56 int x = screen_point.x() + mouse_tab_offset_.x() - |
| 57 ScaleValue(mouse_tab_offset_.x()); |
| 58 int y = screen_point.y() + mouse_tab_offset_.y() - |
| 59 ScaleValue(mouse_tab_offset_.y()); |
| 60 |
| 61 gtk_window_move(GTK_WINDOW(container_.get()), x, y); |
| 62 } |
| 63 |
| 64 void DraggedTabGtk::Attach(int selected_width) { |
| 65 attached_ = true; |
| 66 attached_tab_size_.set_width(selected_width); |
| 67 ResizeContainer(); |
| 68 Update(); |
| 69 } |
| 70 |
| 71 void DraggedTabGtk::Update() { |
| 72 gtk_widget_queue_draw(container_.get()); |
| 73 } |
| 74 |
| 75 void DraggedTabGtk::AnimateToBounds(const gfx::Rect& bounds, |
| 76 AnimateToBoundsCallback* callback) { |
| 77 animation_callback_.reset(callback); |
| 78 |
| 79 gint x, y, width, height; |
| 80 gdk_window_get_origin(container_.get()->window, &x, &y); |
| 81 gdk_window_get_geometry(container_.get()->window, NULL, NULL, |
| 82 &width, &height, NULL); |
| 83 |
| 84 animation_start_bounds_ = gfx::Rect(x, y, width, height); |
| 85 animation_end_bounds_ = bounds; |
| 86 |
| 87 close_animation_.SetSlideDuration(kAnimateToBoundsDurationMs); |
| 88 close_animation_.SetTweenType(SlideAnimation::EASE_OUT); |
| 89 if (!close_animation_.IsShowing()) { |
| 90 close_animation_.Reset(); |
| 91 close_animation_.Show(); |
| 92 } |
| 93 } |
| 94 |
| 95 //////////////////////////////////////////////////////////////////////////////// |
| 96 // DraggedTabGtk, AnimationDelegate implementation: |
| 97 |
| 98 void DraggedTabGtk::AnimationProgressed(const Animation* animation) { |
| 99 int delta_x = (animation_end_bounds_.x() - animation_start_bounds_.x()); |
| 100 int x = animation_start_bounds_.x() + |
| 101 static_cast<int>(delta_x * animation->GetCurrentValue()); |
| 102 int y = animation_end_bounds_.y(); |
| 103 gdk_window_move(container_.get()->window, x, y); |
| 104 } |
| 105 |
| 106 void DraggedTabGtk::AnimationEnded(const Animation* animation) { |
| 107 animation_callback_->Run(); |
| 108 } |
| 109 |
| 110 void DraggedTabGtk::AnimationCanceled(const Animation* animation) { |
| 111 AnimationEnded(animation); |
| 112 } |
| 113 |
| 114 //////////////////////////////////////////////////////////////////////////////// |
| 115 // DraggedTabGtk, private: |
| 116 |
| 117 gfx::Size DraggedTabGtk::GetPreferredSize() { |
| 118 if (attached_) |
| 119 return attached_tab_size_; |
| 120 |
| 121 int width = std::max(attached_tab_size_.width(), contents_size_.width()) + |
| 122 kTwiceDragFrameBorderSize; |
| 123 int height = attached_tab_size_.height() + kDragFrameBorderSize + |
| 124 contents_size_.height(); |
| 125 return gfx::Size(width, height); |
| 126 } |
| 127 |
| 128 void DraggedTabGtk::ResizeContainer() { |
| 129 gfx::Size size = GetPreferredSize(); |
| 130 gtk_window_resize(GTK_WINDOW(container_.get()), |
| 131 ScaleValue(size.width()), ScaleValue(size.height())); |
| 132 gfx::Rect bounds = renderer_->bounds(); |
| 133 bounds.set_width(ScaleValue(size.width())); |
| 134 bounds.set_height(ScaleValue(size.height())); |
| 135 renderer_->SetBounds(bounds); |
| 136 Update(); |
| 137 } |
| 138 |
| 139 int DraggedTabGtk::ScaleValue(int value) { |
| 140 return attached_ ? value : static_cast<int>(value * kScalingFactor); |
| 141 } |
| 142 |
| 143 void DraggedTabGtk::SetContainerColorMap() { |
| 144 GdkScreen* screen = gtk_widget_get_screen(container_.get()); |
| 145 GdkColormap* colormap = gdk_screen_get_rgba_colormap(screen); |
| 146 |
| 147 // If rgba is not available, use rgb instead. |
| 148 if (!colormap) |
| 149 colormap = gdk_screen_get_rgb_colormap(screen); |
| 150 |
| 151 gtk_widget_set_colormap(container_.get(), colormap); |
| 152 } |
| 153 |
| 154 // static |
| 155 gboolean DraggedTabGtk::OnExpose(GtkWidget* widget, GdkEventExpose* event, |
| 156 DraggedTabGtk* dragged_tab) { |
| 157 cairo_t* cairo_context = gdk_cairo_create(widget->window); |
| 158 if (!cairo_context) |
| 159 return FALSE; |
| 160 |
| 161 // Make the background of the dragged tab window fully transparent. All of |
| 162 // the content of the window (child widgets) will be completely opaque. |
| 163 gint width, height; |
| 164 gtk_window_get_size(GTK_WINDOW(widget), &width, &height); |
| 165 cairo_scale(cairo_context, static_cast<double>(width), |
| 166 static_cast<double>(height)); |
| 167 cairo_set_source_rgba(cairo_context, 1.0f, 1.0f, 1.0f, 0.0f); |
| 168 cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE); |
| 169 cairo_paint(cairo_context); |
| 170 cairo_destroy(cairo_context); |
| 171 |
| 172 return FALSE; |
| 173 } |
OLD | NEW |