1/* 2 * Copyright (C) 2011 Igalia S.L. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "DragIcon.h" 28#include "GdkCairoUtilities.h" 29 30#include <gtk/gtk.h> 31 32namespace WebCore { 33 34#ifdef GTK_API_VERSION_2 35static gboolean dragIconWindowDrawEventCallback(GtkWidget*, GdkEventExpose* event, DragIcon* icon) 36{ 37 RefPtr<cairo_t> context = adoptRef(gdk_cairo_create(event->window)); 38 icon->draw(context.get()); 39 return TRUE; 40} 41#else 42static gboolean dragIconWindowDrawEventCallback(GtkWidget*, cairo_t* context, DragIcon* icon) 43{ 44 if (!gdk_cairo_get_clip_rectangle(context, 0)) 45 return FALSE; 46 icon->draw(context); 47 return TRUE; 48} 49#endif // GTK_API_VERSION_2 50 51DragIcon::DragIcon() 52 : isComposited(gdk_screen_is_composited(gdk_screen_get_default())) 53 , m_window(0) 54{ 55 if (!isComposited) 56 return; 57 58 m_window = gtk_window_new(GTK_WINDOW_POPUP); 59#ifdef GTK_API_VERSION_2 60 g_signal_connect(m_window, "expose-event", G_CALLBACK(dragIconWindowDrawEventCallback), this); 61#else 62 g_signal_connect(m_window, "draw", G_CALLBACK(dragIconWindowDrawEventCallback), this); 63#endif 64 65 // This strategy originally comes from Chromium: src/chrome/browser/gtk/tab_contents_drag_source.cc 66 GdkScreen* screen = gtk_widget_get_screen(m_window); 67#ifdef GTK_API_VERSION_2 68 GdkColormap* rgba = gdk_screen_get_rgba_colormap(screen); 69 if (rgba) 70 gtk_widget_set_colormap(m_window, rgba); 71#else 72 GdkVisual* visual = gdk_screen_get_rgba_visual(screen); 73 if (!visual) 74 visual = gdk_screen_get_system_visual(screen); 75 gtk_widget_set_visual(m_window, visual); 76#endif // GTK_API_VERSION_2 77} 78 79DragIcon::~DragIcon() 80{ 81 if (m_window) 82 gtk_widget_destroy(m_window); 83} 84 85void DragIcon::draw(cairo_t* context) 86{ 87 cairo_rectangle(context, 0, 0, 88 cairo_image_surface_get_width(m_image.get()), 89 cairo_image_surface_get_height(m_image.get())); 90 cairo_set_operator(context, CAIRO_OPERATOR_SOURCE); 91 cairo_set_source_surface(context, m_image.get(), 0, 0); 92 cairo_fill(context); 93} 94 95void DragIcon::setImage(cairo_surface_t* image) 96{ 97 ASSERT(image); 98 m_image = image; 99 m_imageSize = IntSize(cairo_image_surface_get_width(image), cairo_image_surface_get_height(image)); 100 if (isComposited) { 101 gtk_window_resize(GTK_WINDOW(m_window), m_imageSize.width(), m_imageSize.height()); 102 return; 103 } 104 105#ifdef GTK_API_VERSION_2 106 m_pixbuf = adoptGRef(cairoImageSurfaceToGdkPixbuf(image)); 107#endif 108} 109 110void DragIcon::useForDrag(GdkDragContext* context) 111{ 112 IntPoint hotspot(m_imageSize); 113 hotspot.scale(0.5, 0.5); 114 useForDrag(context, hotspot); 115} 116 117void DragIcon::useForDrag(GdkDragContext* context, const IntPoint& hotspot) 118{ 119 if (isComposited) { 120 gtk_drag_set_icon_widget(context, m_window, hotspot.x(), hotspot.y()); 121 return; 122 } 123#ifdef GTK_API_VERSION_2 124 gtk_drag_set_icon_pixbuf(context, m_pixbuf.get(), hotspot.x(), hotspot.y()); 125#else 126 gtk_drag_set_icon_surface(context, m_image.get()); 127#endif 128} 129 130} // namespace WebCore 131