Index: chrome/browser/gtk/tabs/dragged_tab_gtk.cc |
=================================================================== |
--- chrome/browser/gtk/tabs/dragged_tab_gtk.cc (revision 0) |
+++ chrome/browser/gtk/tabs/dragged_tab_gtk.cc (revision 0) |
@@ -0,0 +1,173 @@ |
+// Copyright (c) 2009 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/gtk/tabs/dragged_tab_gtk.h" |
+ |
+#include <gdk/gdk.h> |
+ |
+#include "app/gfx/canvas.h" |
+#include "chrome/browser/tab_contents/tab_contents.h" |
+#include "chrome/browser/tabs/tab_strip_model.h" |
+#include "chrome/browser/gtk/tabs/tab_renderer_gtk.h" |
+#include "third_party/skia/include/core/SkShader.h" |
+ |
+namespace { |
+ |
+// The size of the dragged window frame. |
+const int kDragFrameBorderSize = 2; |
+const int kTwiceDragFrameBorderSize = 2 * kDragFrameBorderSize; |
+ |
+// Used to scale the dragged window sizes. |
+const float kScalingFactor = 0.5; |
+ |
+const int kAnimateToBoundsDurationMs = 150; |
+ |
+} // namespace |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// DraggedTabGtk, public: |
+ |
+DraggedTabGtk::DraggedTabGtk(TabContents* datasource, |
+ const gfx::Point& mouse_tab_offset, |
+ const gfx::Size& contents_size) |
+ : renderer_(new TabRendererGtk), |
+ attached_(false), |
+ mouse_tab_offset_(mouse_tab_offset), |
+ attached_tab_size_(TabRendererGtk::GetMinimumSelectedSize()), |
+ contents_size_(contents_size), |
+ close_animation_(this) { |
+ renderer_->UpdateData(datasource, false); |
+ |
+ container_.Own(gtk_window_new(GTK_WINDOW_POPUP)); |
+ SetContainerColorMap(); |
+ gtk_widget_set_app_paintable(container_.get(), TRUE); |
+ g_signal_connect(G_OBJECT(container_.get()), "expose-event", |
+ G_CALLBACK(OnExpose), this); |
+ gtk_container_add(GTK_CONTAINER(container_.get()), renderer_->widget()); |
+ gtk_widget_show_all(container_.get()); |
+} |
+ |
+DraggedTabGtk::~DraggedTabGtk() { |
+ gtk_widget_destroy(container_.get()); |
+} |
+ |
+void DraggedTabGtk::MoveTo(const gfx::Point& screen_point) { |
+ int x = screen_point.x() + mouse_tab_offset_.x() - |
+ ScaleValue(mouse_tab_offset_.x()); |
+ int y = screen_point.y() + mouse_tab_offset_.y() - |
+ ScaleValue(mouse_tab_offset_.y()); |
+ |
+ gtk_window_move(GTK_WINDOW(container_.get()), x, y); |
+} |
+ |
+void DraggedTabGtk::Attach(int selected_width) { |
+ attached_ = true; |
+ attached_tab_size_.set_width(selected_width); |
+ ResizeContainer(); |
+ Update(); |
+} |
+ |
+void DraggedTabGtk::Update() { |
+ gtk_widget_queue_draw(container_.get()); |
+} |
+ |
+void DraggedTabGtk::AnimateToBounds(const gfx::Rect& bounds, |
+ AnimateToBoundsCallback* callback) { |
+ animation_callback_.reset(callback); |
+ |
+ gint x, y, width, height; |
+ gdk_window_get_origin(container_.get()->window, &x, &y); |
+ gdk_window_get_geometry(container_.get()->window, NULL, NULL, |
+ &width, &height, NULL); |
+ |
+ animation_start_bounds_ = gfx::Rect(x, y, width, height); |
+ animation_end_bounds_ = bounds; |
+ |
+ close_animation_.SetSlideDuration(kAnimateToBoundsDurationMs); |
+ close_animation_.SetTweenType(SlideAnimation::EASE_OUT); |
+ if (!close_animation_.IsShowing()) { |
+ close_animation_.Reset(); |
+ close_animation_.Show(); |
+ } |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// DraggedTabGtk, AnimationDelegate implementation: |
+ |
+void DraggedTabGtk::AnimationProgressed(const Animation* animation) { |
+ int delta_x = (animation_end_bounds_.x() - animation_start_bounds_.x()); |
+ int x = animation_start_bounds_.x() + |
+ static_cast<int>(delta_x * animation->GetCurrentValue()); |
+ int y = animation_end_bounds_.y(); |
+ gdk_window_move(container_.get()->window, x, y); |
+} |
+ |
+void DraggedTabGtk::AnimationEnded(const Animation* animation) { |
+ animation_callback_->Run(); |
+} |
+ |
+void DraggedTabGtk::AnimationCanceled(const Animation* animation) { |
+ AnimationEnded(animation); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// DraggedTabGtk, private: |
+ |
+gfx::Size DraggedTabGtk::GetPreferredSize() { |
+ if (attached_) |
+ return attached_tab_size_; |
+ |
+ int width = std::max(attached_tab_size_.width(), contents_size_.width()) + |
+ kTwiceDragFrameBorderSize; |
+ int height = attached_tab_size_.height() + kDragFrameBorderSize + |
+ contents_size_.height(); |
+ return gfx::Size(width, height); |
+} |
+ |
+void DraggedTabGtk::ResizeContainer() { |
+ gfx::Size size = GetPreferredSize(); |
+ gtk_window_resize(GTK_WINDOW(container_.get()), |
+ ScaleValue(size.width()), ScaleValue(size.height())); |
+ gfx::Rect bounds = renderer_->bounds(); |
+ bounds.set_width(ScaleValue(size.width())); |
+ bounds.set_height(ScaleValue(size.height())); |
+ renderer_->SetBounds(bounds); |
+ Update(); |
+} |
+ |
+int DraggedTabGtk::ScaleValue(int value) { |
+ return attached_ ? value : static_cast<int>(value * kScalingFactor); |
+} |
+ |
+void DraggedTabGtk::SetContainerColorMap() { |
+ GdkScreen* screen = gtk_widget_get_screen(container_.get()); |
+ GdkColormap* colormap = gdk_screen_get_rgba_colormap(screen); |
+ |
+ // If rgba is not available, use rgb instead. |
+ if (!colormap) |
+ colormap = gdk_screen_get_rgb_colormap(screen); |
+ |
+ gtk_widget_set_colormap(container_.get(), colormap); |
+} |
+ |
+// static |
+gboolean DraggedTabGtk::OnExpose(GtkWidget* widget, GdkEventExpose* event, |
+ DraggedTabGtk* dragged_tab) { |
+ cairo_t* cairo_context = gdk_cairo_create(widget->window); |
+ if (!cairo_context) |
+ return FALSE; |
+ |
+ // Make the background of the dragged tab window fully transparent. All of |
+ // the content of the window (child widgets) will be completely opaque. |
+ gint width, height; |
+ gtk_window_get_size(GTK_WINDOW(widget), &width, &height); |
+ cairo_scale(cairo_context, static_cast<double>(width), |
+ static_cast<double>(height)); |
+ cairo_set_source_rgba(cairo_context, 1.0f, 1.0f, 1.0f, 0.0f); |
+ cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE); |
+ cairo_paint(cairo_context); |
+ cairo_destroy(cairo_context); |
+ |
+ return FALSE; |
+} |