18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 2a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2009, 2010 Igalia S.L. 321939df44de1705786c545cd1bf519d47250322dBen Murdoch * 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Lesser General Public 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2 of the License, or (at your option) any later version. 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful, 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Lesser General Public License for more details. 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Lesser General Public 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License along with this library; if not, write to the Free Software 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "DragClientGtk.h" 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 2221939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "ClipboardGtk.h" 23e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "ClipboardUtilitiesGtk.h" 2421939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "DataObjectGtk.h" 25231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "Document.h" 26e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block#include "DragController.h" 27231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "Element.h" 28231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "Frame.h" 29545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch#include "GOwnPtrGtk.h" 3021939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "GRefPtrGtk.h" 31545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch#include "GtkVersioning.h" 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "NotImplemented.h" 3321939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "PasteboardHelper.h" 34231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "RenderObject.h" 35f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "webkitwebframeprivate.h" 36f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "webkitwebviewprivate.h" 37231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "webkitwebview.h" 3868513a70bcd92384395513322f1b801e7bf9c729Steve Block#include <gdk/gdk.h> 39231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <gtk/gtk.h> 408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace WebCore; 428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebKit { 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 45a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#ifdef GTK_API_VERSION_2 46a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochstatic gboolean dragIconWindowDrawEventCallback(GtkWidget* widget, GdkEventExpose* event, DragClient* client) 4768513a70bcd92384395513322f1b801e7bf9c729Steve Block{ 4828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu RefPtr<cairo_t> context = adoptRef(gdk_cairo_create(event->window)); 49a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch client->drawDragIconWindow(widget, context.get()); 5068513a70bcd92384395513322f1b801e7bf9c729Steve Block return TRUE; 5168513a70bcd92384395513322f1b801e7bf9c729Steve Block} 52a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#else 53a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochstatic gboolean dragIconWindowDrawEventCallback(GtkWidget* widget, cairo_t* context, DragClient* client) 54a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 55a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!gdk_cairo_get_clip_rectangle(context, 0)) 56a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return FALSE; 57a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch client->drawDragIconWindow(widget, context); 58a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return TRUE; 59a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 60a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif // GTK_API_VERSION_2 6168513a70bcd92384395513322f1b801e7bf9c729Steve Block 62231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockDragClient::DragClient(WebKitWebView* webView) 63231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block : m_webView(webView) 64231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block , m_startPos(0, 0) 6568513a70bcd92384395513322f1b801e7bf9c729Steve Block , m_dragIconWindow(gtk_window_new(GTK_WINDOW_POPUP)) 66231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 67a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#ifdef GTK_API_VERSION_2 6865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch g_signal_connect(m_dragIconWindow, "expose-event", G_CALLBACK(dragIconWindowDrawEventCallback), this); 69a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#else 7065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch g_signal_connect(m_dragIconWindow, "draw", G_CALLBACK(dragIconWindowDrawEventCallback), this); 71a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif 7268513a70bcd92384395513322f1b801e7bf9c729Steve Block} 7368513a70bcd92384395513322f1b801e7bf9c729Steve Block 7468513a70bcd92384395513322f1b801e7bf9c729Steve BlockDragClient::~DragClient() 7568513a70bcd92384395513322f1b801e7bf9c729Steve Block{ 7665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch gtk_widget_destroy(m_dragIconWindow); 77231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 78231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid DragClient::willPerformDragDestinationAction(DragDestinationAction, DragData*) 808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 83231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid DragClient::willPerformDragSourceAction(DragSourceAction, const IntPoint& startPos, Clipboard*) 848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 85231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block m_startPos = startPos; 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectDragDestinationAction DragClient::actionMaskForDrag(DragData*) 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notImplemented(); 918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return DragDestinationActionAny; 928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectDragSourceAction DragClient::dragSourceActionMaskForPoint(const IntPoint&) 958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project notImplemented(); 978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return DragSourceActionAny; 988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 10021939df44de1705786c545cd1bf519d47250322dBen Murdochvoid DragClient::startDrag(DragImageRef image, const IntPoint& dragImageOrigin, const IntPoint& eventPos, Clipboard* clipboard, Frame* frame, bool linkDrag) 1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 10221939df44de1705786c545cd1bf519d47250322dBen Murdoch ClipboardGtk* clipboardGtk = reinterpret_cast<ClipboardGtk*>(clipboard); 103231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 10421939df44de1705786c545cd1bf519d47250322dBen Murdoch WebKitWebView* webView = webkit_web_frame_get_web_view(kit(frame)); 10521939df44de1705786c545cd1bf519d47250322dBen Murdoch RefPtr<DataObjectGtk> dataObject = clipboardGtk->dataObject(); 106cad810f21b803229eb11403f9209855525a25d57Steve Block GRefPtr<GtkTargetList> targetList(clipboardGtk->helper()->targetListForDataObject(dataObject.get())); 107545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch GOwnPtr<GdkEvent> currentEvent(gtk_get_current_event()); 108231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 109545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch GdkDragContext* context = gtk_drag_begin(GTK_WIDGET(m_webView), targetList.get(), dragOperationToGdkDragActions(clipboard->sourceOperation()), 1, currentEvent.get()); 11068513a70bcd92384395513322f1b801e7bf9c729Steve Block webView->priv->draggingDataObjects.set(context, dataObject); 111231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 11206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen // A drag starting should prevent a double-click from happening. This might 11306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen // happen if a drag is followed very quickly by another click (like in the DRT). 11406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen webView->priv->previousClickTime = 0; 11506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 11668513a70bcd92384395513322f1b801e7bf9c729Steve Block // This strategy originally comes from Chromium: 11768513a70bcd92384395513322f1b801e7bf9c729Steve Block // src/chrome/browser/gtk/tab_contents_drag_source.cc 11868513a70bcd92384395513322f1b801e7bf9c729Steve Block if (image) { 11968513a70bcd92384395513322f1b801e7bf9c729Steve Block m_dragImage = image; 12068513a70bcd92384395513322f1b801e7bf9c729Steve Block IntSize imageSize(cairo_image_surface_get_width(image), cairo_image_surface_get_height(image)); 12165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch gtk_window_resize(GTK_WINDOW(m_dragIconWindow), imageSize.width(), imageSize.height()); 12268513a70bcd92384395513322f1b801e7bf9c729Steve Block 12365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if (!gtk_widget_get_realized(m_dragIconWindow)) { 12465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch GdkScreen* screen = gtk_widget_get_screen(m_dragIconWindow); 125a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#ifdef GTK_API_VERSION_2 12668513a70bcd92384395513322f1b801e7bf9c729Steve Block GdkColormap* rgba = gdk_screen_get_rgba_colormap(screen); 12768513a70bcd92384395513322f1b801e7bf9c729Steve Block if (rgba) 12865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch gtk_widget_set_colormap(m_dragIconWindow, rgba); 129a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#else 130a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch GdkVisual* visual = gdk_screen_get_rgba_visual(screen); 131a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!visual) 132a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch visual = gdk_screen_get_system_visual(screen); 13365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch gtk_widget_set_visual(m_dragIconWindow, visual); 134a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif // GTK_API_VERSION_2 13568513a70bcd92384395513322f1b801e7bf9c729Steve Block } 13668513a70bcd92384395513322f1b801e7bf9c729Steve Block 13768513a70bcd92384395513322f1b801e7bf9c729Steve Block IntSize origin = eventPos - dragImageOrigin; 13865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch gtk_drag_set_icon_widget(context, m_dragIconWindow, 13968513a70bcd92384395513322f1b801e7bf9c729Steve Block origin.width(), origin.height()); 14068513a70bcd92384395513322f1b801e7bf9c729Steve Block } else 141231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block gtk_drag_set_icon_default(context); 1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 144a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid DragClient::drawDragIconWindow(GtkWidget* widget, cairo_t* context) 14568513a70bcd92384395513322f1b801e7bf9c729Steve Block{ 146a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch cairo_rectangle(context, 0, 0, 14768513a70bcd92384395513322f1b801e7bf9c729Steve Block cairo_image_surface_get_width(m_dragImage.get()), 14868513a70bcd92384395513322f1b801e7bf9c729Steve Block cairo_image_surface_get_height(m_dragImage.get())); 149a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch cairo_set_operator(context, CAIRO_OPERATOR_SOURCE); 150a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch cairo_set_source_surface(context, m_dragImage.get(), 0, 0); 151a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch cairo_fill(context); 15268513a70bcd92384395513322f1b801e7bf9c729Steve Block} 15368513a70bcd92384395513322f1b801e7bf9c729Steve Block 1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid DragClient::dragControllerDestroyed() 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project delete this; 1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 159