diff options
-rw-r--r-- | chrome/browser/gtk/tabs/dragged_tab_gtk.cc | 158 | ||||
-rw-r--r-- | chrome/browser/gtk/tabs/dragged_tab_gtk.h | 15 | ||||
-rw-r--r-- | chrome/browser/renderer_host/backing_store.h | 6 | ||||
-rw-r--r-- | chrome/browser/renderer_host/backing_store_x.cc | 29 |
4 files changed, 117 insertions, 91 deletions
diff --git a/chrome/browser/gtk/tabs/dragged_tab_gtk.cc b/chrome/browser/gtk/tabs/dragged_tab_gtk.cc index 8e829ec..aab4b8c 100644 --- a/chrome/browser/gtk/tabs/dragged_tab_gtk.cc +++ b/chrome/browser/gtk/tabs/dragged_tab_gtk.cc @@ -14,12 +14,13 @@ #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/gtk/tabs/tab_renderer_gtk.h" #include "chrome/common/gtk_util.h" +#include "chrome/common/x11_util.h" #include "third_party/skia/include/core/SkShader.h" namespace { // The size of the dragged window frame. -const int kDragFrameBorderSize = 2; +const int kDragFrameBorderSize = 1; const int kTwiceDragFrameBorderSize = 2 * kDragFrameBorderSize; // Used to scale the dragged window sizes. @@ -29,7 +30,9 @@ const int kAnimateToBoundsDurationMs = 150; const gdouble kTransparentAlpha = (200.0f / 255.0f); const gdouble kOpaqueAlpha = 1.0f; -const SkColor kDraggedTabBorderColor = SkColorSetRGB(103, 129, 162); +const double kDraggedTabBorderColor[] = { 103.0 / 0xff, + 129.0 / 0xff, + 162.0 / 0xff }; } // namespace @@ -196,7 +199,7 @@ void DraggedTabGtk::SetContainerColorMap() { void DraggedTabGtk::SetContainerTransparency() { cairo_t* cairo_context = gdk_cairo_create(container_->window); if (!cairo_context) - return; + return; // Make the background of the dragged tab window fully transparent. All of // the content of the window (child widgets) will be completely opaque. @@ -209,9 +212,7 @@ void DraggedTabGtk::SetContainerTransparency() { cairo_destroy(cairo_context); } -void DraggedTabGtk::SetContainerShapeMask(const SkBitmap& dragged_contents) { - GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&dragged_contents); - +void DraggedTabGtk::SetContainerShapeMask(GdkPixbuf* pixbuf) { // Create a 1bpp bitmap the size of |container_|. gfx::Size size = bounds().size(); GdkPixmap* pixmap = gdk_pixmap_new(NULL, size.width(), size.height(), 1); @@ -223,100 +224,97 @@ void DraggedTabGtk::SetContainerShapeMask(const SkBitmap& dragged_contents) { // Blit the rendered bitmap into a pixmap. Any pixel set in the pixmap will // be opaque in the container window. cairo_set_operator(cairo_context, CAIRO_OPERATOR_SOURCE); + if (!attached_) + cairo_scale(cairo_context, kScalingFactor, kScalingFactor); gdk_cairo_set_source_pixbuf(cairo_context, pixbuf, 0, 0); cairo_paint(cairo_context); + + if (!attached_) { + // Make the render area depiction opaque (leaving enough room for the + // border). + cairo_identity_matrix(cairo_context); + cairo_set_source_rgba(cairo_context, 1.0f, 1.0f, 1.0f, 1.0f); + int tab_height = kScalingFactor * gdk_pixbuf_get_height(pixbuf) - + kDragFrameBorderSize; + cairo_rectangle(cairo_context, + 0, tab_height, + size.width(), size.height() - tab_height); + cairo_fill(cairo_context); + } + cairo_destroy(cairo_context); // Set the shape mask. gdk_window_shape_combine_mask(container_->window, pixmap, 0, 0); - g_object_unref(pixbuf); g_object_unref(pixmap); } -SkBitmap DraggedTabGtk::PaintAttachedTab() { - return renderer_->PaintBitmap(); -} - -SkBitmap DraggedTabGtk::PaintDetachedView() { - gfx::Size ps = GetPreferredSize(); - gfx::Canvas scale_canvas(ps.width(), ps.height(), false); - SkBitmap& bitmap_device = const_cast<SkBitmap&>( - scale_canvas.getTopPlatformDevice().accessBitmap(true)); - bitmap_device.eraseARGB(0, 0, 0, 0); - - scale_canvas.FillRectInt(kDraggedTabBorderColor, 0, - attached_tab_size_.height() - kDragFrameBorderSize, - ps.width(), ps.height() - attached_tab_size_.height()); - int image_x = kDragFrameBorderSize; - int image_y = attached_tab_size_.height(); - int image_w = ps.width() - kTwiceDragFrameBorderSize; - int image_h = - ps.height() - kTwiceDragFrameBorderSize - attached_tab_size_.height(); - scale_canvas.FillRectInt(SK_ColorBLACK, image_x, image_y, image_w, image_h); - PaintScreenshotIntoCanvas(&scale_canvas, - gfx::Rect(image_x, image_y, image_w, image_h)); - renderer_->Paint(&scale_canvas); - - SkIRect subset; - subset.set(0, 0, ps.width(), ps.height()); - SkBitmap mipmap = scale_canvas.ExtractBitmap(); - mipmap.buildMipMap(true); - - SkShader* bitmap_shader = - SkShader::CreateBitmapShader(mipmap, SkShader::kClamp_TileMode, - SkShader::kClamp_TileMode); - - SkMatrix shader_scale; - shader_scale.setScale(kScalingFactor, kScalingFactor); - bitmap_shader->setLocalMatrix(shader_scale); - - SkPaint paint; - paint.setShader(bitmap_shader); - paint.setAntiAlias(true); - bitmap_shader->unref(); - - SkRect rc; - rc.fLeft = 0; - rc.fTop = 0; - rc.fRight = SkIntToScalar(ps.width()); - rc.fBottom = SkIntToScalar(ps.height()); - gfx::Canvas canvas(ps.width(), ps.height(), false); - canvas.drawRect(rc, paint); - - return canvas.ExtractBitmap(); -} - -void DraggedTabGtk::PaintScreenshotIntoCanvas(gfx::Canvas* canvas, - const gfx::Rect& target_bounds) { - // A drag could be initiated before the backing store is created. - if (!backing_store_) - return; - - gfx::Rect rect(0, 0, target_bounds.width(), target_bounds.height()); - SkBitmap bitmap = backing_store_->PaintRectToBitmap(rect); - if (!bitmap.isNull()) - canvas->DrawBitmapInt(bitmap, target_bounds.x(), target_bounds.y()); +GdkPixbuf* DraggedTabGtk::PaintTab() { + SkBitmap bitmap = renderer_->PaintBitmap(); + return gfx::GdkPixbufFromSkBitmap(&bitmap); } // static gboolean DraggedTabGtk::OnExposeEvent(GtkWidget* widget, GdkEventExpose* event, DraggedTabGtk* dragged_tab) { - SkBitmap bmp; - if (dragged_tab->attached_) { - bmp = dragged_tab->PaintAttachedTab(); - } else { - bmp = dragged_tab->PaintDetachedView(); - } - + GdkPixbuf* pixbuf = dragged_tab->PaintTab(); if (gtk_util::IsScreenComposited()) { dragged_tab->SetContainerTransparency(); } else { - dragged_tab->SetContainerShapeMask(bmp); + dragged_tab->SetContainerShapeMask(pixbuf); + } + + // Only used when not attached. + int tab_height = kScalingFactor * gdk_pixbuf_get_height(pixbuf); + int tab_width = kScalingFactor * gdk_pixbuf_get_width(pixbuf); + + // Draw the render area. + if (dragged_tab->backing_store_ && !dragged_tab->attached_) { + // This leaves room for the border. + dragged_tab->backing_store_->PaintToRect( + gfx::Rect(kDragFrameBorderSize, tab_height, + widget->allocation.width - kTwiceDragFrameBorderSize, + widget->allocation.height - tab_height - + kDragFrameBorderSize), + GDK_DRAWABLE(widget->window)); } - gfx::CanvasPaint canvas(event, false); - canvas.DrawBitmapInt(bmp, 0, 0); + cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window)); + // Draw the border. + if (!dragged_tab->attached_) { + cairo_set_line_width(cr, kDragFrameBorderSize); + cairo_set_source_rgb(cr, kDraggedTabBorderColor[0], + kDraggedTabBorderColor[1], + kDraggedTabBorderColor[2]); + // |offset| is the distance from the edge of the image to the middle of + // the border line. + double offset = kDragFrameBorderSize / 2.0 - 0.5; + double left_x = offset; + double top_y = tab_height - kDragFrameBorderSize + offset; + double right_x = widget->allocation.width - offset; + double bottom_y = widget->allocation.height - offset; + double middle_x = tab_width + offset; + + // We don't use cairo_rectangle() because we don't want to draw the border + // under the tab itself. + cairo_move_to(cr, left_x, top_y); + cairo_line_to(cr, left_x, bottom_y); + cairo_line_to(cr, right_x, bottom_y); + cairo_line_to(cr, right_x, top_y); + cairo_line_to(cr, middle_x, top_y); + cairo_stroke(cr); + } + + // Draw the tab. + if (!dragged_tab->attached_) + cairo_scale(cr, kScalingFactor, kScalingFactor); + gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0); + cairo_paint(cr); + + cairo_destroy(cr); + + g_object_unref(pixbuf); // We've already drawn the tab, so don't propagate the expose-event signal. return TRUE; diff --git a/chrome/browser/gtk/tabs/dragged_tab_gtk.h b/chrome/browser/gtk/tabs/dragged_tab_gtk.h index fb5a303..0732a12 100644 --- a/chrome/browser/gtk/tabs/dragged_tab_gtk.h +++ b/chrome/browser/gtk/tabs/dragged_tab_gtk.h @@ -86,18 +86,11 @@ class DraggedTabGtk : public AnimationDelegate { // Sets the shape mask for the container window to emulate a transparent // container window. This is used if compositing is not available for the // screen. - void SetContainerShapeMask(const SkBitmap& dragged_contents); + // |pixbuf| is the pixbuf for the tab only (not the render view). + void SetContainerShapeMask(GdkPixbuf* pixbuf); - // Paints the tab when it's attached to a tabstrip. - SkBitmap PaintAttachedTab(); - - // Paints the tab when it's not attached to any tabstrip. - SkBitmap PaintDetachedView(); - - // Paints a screenshot of the dragged contents from the backing store into - // |canvas|. - void PaintScreenshotIntoCanvas(gfx::Canvas* canvas, - const gfx::Rect& target_bounds); + // Paints the tab. The returned pixbuf belongs to the caller. + GdkPixbuf* PaintTab(); // expose-event handler that notifies when the tab needs to be redrawn. static gboolean OnExposeEvent(GtkWidget* widget, GdkEventExpose* event, diff --git a/chrome/browser/renderer_host/backing_store.h b/chrome/browser/renderer_host/backing_store.h index 1114a18..49922e78 100644 --- a/chrome/browser/renderer_host/backing_store.h +++ b/chrome/browser/renderer_host/backing_store.h @@ -23,6 +23,7 @@ class RenderWidgetHost; class SkBitmap; class TransportDIB; +typedef struct _GdkDrawable GdkDrawable; // BackingStore ---------------------------------------------------------------- @@ -75,6 +76,11 @@ class BackingStore { SkBitmap PaintRectToBitmap(const gfx::Rect& rect); #endif +#if defined(TOOLKIT_GTK) + // Paint the backing store into the target's |dest_rect|. + void PaintToRect(const gfx::Rect& dest_rect, GdkDrawable* target); +#endif + // Paints the bitmap from the renderer onto the backing store. void PaintRect(base::ProcessHandle process, TransportDIB* bitmap, diff --git a/chrome/browser/renderer_host/backing_store_x.cc b/chrome/browser/renderer_host/backing_store_x.cc index 8a8d23f..c1ddad9 100644 --- a/chrome/browser/renderer_host/backing_store_x.cc +++ b/chrome/browser/renderer_host/backing_store_x.cc @@ -7,6 +7,10 @@ #include <stdlib.h> #include <sys/ipc.h> #include <sys/shm.h> +#if defined(TOOLKIT_GTK) +#include <cairo-xlib.h> +#include <gtk/gtk.h> +#endif #include <algorithm> #include <utility> @@ -336,6 +340,31 @@ void BackingStore::ShowRect(const gfx::Rect& rect, XID target) { rect.x(), rect.y()); } +#if defined(TOOLKIT_GTK) +void BackingStore::PaintToRect(const gfx::Rect& rect, GdkDrawable* target) { + cairo_surface_t* surface = cairo_xlib_surface_create( + display_, pixmap_, static_cast<Visual*>(visual_), + size_.width(), size_.height()); + cairo_t* cr = gdk_cairo_create(target); + + cairo_translate(cr, rect.x(), rect.y()); + double x_scale = static_cast<double>(rect.width()) / size_.width(); + double y_scale = static_cast<double>(rect.height()) / size_.height(); + cairo_scale(cr, x_scale, y_scale); + + cairo_pattern_t* pattern = cairo_pattern_create_for_surface(surface); + cairo_pattern_set_filter(pattern, CAIRO_FILTER_BEST); + cairo_set_source(cr, pattern); + cairo_pattern_destroy(pattern); + + cairo_identity_matrix(cr); + + cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height()); + cairo_fill(cr); + cairo_destroy(cr); +} +#endif + SkBitmap BackingStore::PaintRectToBitmap(const gfx::Rect& rect) { base::TimeTicks begin_time = base::TimeTicks::Now(); const int width = std::min(size_.width(), rect.width()); |