mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
- Linux: Add support for HTML5 drag&drop (issue #40).
- Linux: Fix GTK cefclient to properly shutdown on CTRL+c (issue #40). - Linux: Fix compile error due to v8_impl.cc revision 469 changes. git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@475 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
4
cef.gyp
4
cef.gyp
@@ -845,6 +845,10 @@
|
|||||||
'libcef/external_protocol_handler_gtk.cc',
|
'libcef/external_protocol_handler_gtk.cc',
|
||||||
'libcef/webview_host_gtk.cc',
|
'libcef/webview_host_gtk.cc',
|
||||||
'libcef/webwidget_host_gtk.cc',
|
'libcef/webwidget_host_gtk.cc',
|
||||||
|
'libcef/web_drag_source_gtk.cc',
|
||||||
|
'libcef/web_drag_source_gtk.h',
|
||||||
|
'libcef/web_drop_target_gtk.cc',
|
||||||
|
'libcef/web_drop_target_gtk.h',
|
||||||
],
|
],
|
||||||
}],
|
}],
|
||||||
],
|
],
|
||||||
|
4
cef.gypi
4
cef.gypi
@@ -19,6 +19,10 @@
|
|||||||
# Don't use the chrome style plugin with CEF.
|
# Don't use the chrome style plugin with CEF.
|
||||||
'clang_use_chrome_plugins': 0,
|
'clang_use_chrome_plugins': 0,
|
||||||
}],
|
}],
|
||||||
|
[ 'OS=="linux"', {
|
||||||
|
# Required for drag and drop helpers.
|
||||||
|
'toolkit_views': 1,
|
||||||
|
}],
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2011 The Chromium Embedded Framework Authors.
|
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
||||||
// Portions copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
// Portions copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
@@ -96,6 +96,9 @@ bool CefBrowserImpl::UIT_CreateBrowser(const CefString& url) {
|
|||||||
g_signal_connect(G_OBJECT(window_info_.m_Widget), "destroy",
|
g_signal_connect(G_OBJECT(window_info_.m_Widget), "destroy",
|
||||||
G_CALLBACK(window_destroyed), this);
|
G_CALLBACK(window_destroyed), this);
|
||||||
|
|
||||||
|
if (!settings_.drag_drop_disabled)
|
||||||
|
delegate_->RegisterDragDrop();
|
||||||
|
|
||||||
Unlock();
|
Unlock();
|
||||||
|
|
||||||
if (client_.get()) {
|
if (client_.get()) {
|
||||||
|
@@ -8,6 +8,9 @@
|
|||||||
// have initialized a MessageLoop before these methods are called.
|
// have initialized a MessageLoop before these methods are called.
|
||||||
|
|
||||||
#include "libcef/browser_webview_delegate.h"
|
#include "libcef/browser_webview_delegate.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "libcef/browser_appcache_system.h"
|
#include "libcef/browser_appcache_system.h"
|
||||||
#include "libcef/browser_file_system.h"
|
#include "libcef/browser_file_system.h"
|
||||||
#include "libcef/browser_impl.h"
|
#include "libcef/browser_impl.h"
|
||||||
@@ -77,6 +80,11 @@
|
|||||||
#include "libcef/web_drop_target_win.h"
|
#include "libcef/web_drop_target_win.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(OS_LINUX)
|
||||||
|
#include "libcef/web_drag_source_gtk.h"
|
||||||
|
#include "libcef/web_drop_target_gtk.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
using appcache::WebApplicationCacheHostImpl;
|
using appcache::WebApplicationCacheHostImpl;
|
||||||
using WebKit::WebApplicationCacheHost;
|
using WebKit::WebApplicationCacheHost;
|
||||||
using WebKit::WebApplicationCacheHostClient;
|
using WebKit::WebApplicationCacheHostClient;
|
||||||
|
@@ -46,6 +46,11 @@ class BrowserDragDelegate;
|
|||||||
class WebDropTarget;
|
class WebDropTarget;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(OS_LINUX)
|
||||||
|
class WebDragSource;
|
||||||
|
class WebDropTarget;
|
||||||
|
#endif
|
||||||
|
|
||||||
class CefBrowserImpl;
|
class CefBrowserImpl;
|
||||||
class GURL;
|
class GURL;
|
||||||
class WebWidgetHost;
|
class WebWidgetHost;
|
||||||
@@ -229,9 +234,11 @@ class BrowserWebViewDelegate : public WebKit::WebViewClient,
|
|||||||
void SetSelectTrailingWhitespaceEnabled(bool enabled);
|
void SetSelectTrailingWhitespaceEnabled(bool enabled);
|
||||||
|
|
||||||
// Additional accessors
|
// Additional accessors
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN) || defined(OS_LINUX)
|
||||||
// Sets the webview as a drop target.
|
// Sets the webview as a drop target.
|
||||||
void RegisterDragDrop();
|
void RegisterDragDrop();
|
||||||
|
#endif
|
||||||
|
#if defined(OS_WIN)
|
||||||
void RevokeDragDrop();
|
void RevokeDragDrop();
|
||||||
|
|
||||||
// Called after dragging has finished.
|
// Called after dragging has finished.
|
||||||
@@ -343,6 +350,8 @@ class BrowserWebViewDelegate : public WebKit::WebViewClient,
|
|||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
// Classes needed by drag and drop.
|
// Classes needed by drag and drop.
|
||||||
scoped_refptr<BrowserDragDelegate> drag_delegate_;
|
scoped_refptr<BrowserDragDelegate> drag_delegate_;
|
||||||
|
#endif
|
||||||
|
#if defined(OS_WIN) || defined(OS_LINUX)
|
||||||
scoped_refptr<WebDropTarget> drop_target_;
|
scoped_refptr<WebDropTarget> drop_target_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -351,6 +360,7 @@ class BrowserWebViewDelegate : public WebKit::WebViewClient,
|
|||||||
// Used for judging whether a new SetCursor call is actually changing the
|
// Used for judging whether a new SetCursor call is actually changing the
|
||||||
// cursor.
|
// cursor.
|
||||||
GdkCursorType cursor_type_;
|
GdkCursorType cursor_type_;
|
||||||
|
scoped_refptr<WebDragSource> drag_source_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(OS_MACOSX)
|
#if defined(OS_MACOSX)
|
||||||
|
@@ -1,10 +1,13 @@
|
|||||||
// Copyright (c) 2011 The Chromium Embedded Framework Authors.
|
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
||||||
// Portions copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
// Portions copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "libcef/browser_webview_delegate.h"
|
#include "libcef/browser_webview_delegate.h"
|
||||||
#include "libcef/browser_impl.h"
|
#include "libcef/browser_impl.h"
|
||||||
|
#include "libcef/drag_data_impl.h"
|
||||||
|
#include "libcef/web_drop_target_gtk.h"
|
||||||
|
#include "libcef/web_drag_source_gtk.h"
|
||||||
|
|
||||||
#include "base/message_loop.h"
|
#include "base/message_loop.h"
|
||||||
#include "base/string_util.h"
|
#include "base/string_util.h"
|
||||||
@@ -292,9 +295,28 @@ void BrowserWebViewDelegate::startDragging(
|
|||||||
WebDragOperationsMask mask,
|
WebDragOperationsMask mask,
|
||||||
const WebImage& image,
|
const WebImage& image,
|
||||||
const WebPoint& image_offset) {
|
const WebPoint& image_offset) {
|
||||||
// TODO(port): Support drag and drop.
|
|
||||||
if (browser_->UIT_GetWebView())
|
if (browser_->settings().drag_drop_disabled) {
|
||||||
browser_->UIT_GetWebView()->dragSourceSystemDragEnded();
|
browser_->UIT_GetWebView()->dragSourceSystemDragEnded();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebDropData drop_data(data);
|
||||||
|
|
||||||
|
CefRefPtr<CefClient> client = browser_->GetClient();
|
||||||
|
if (client.get()) {
|
||||||
|
CefRefPtr<CefDragHandler> handler = client->GetDragHandler();
|
||||||
|
if (handler.get()) {
|
||||||
|
CefRefPtr<CefDragData> data(new CefDragDataImpl(drop_data));
|
||||||
|
if (handler->OnDragStart(browser_, data,
|
||||||
|
static_cast<CefDragHandler::DragOperationsMask>(mask))) {
|
||||||
|
browser_->UIT_GetWebView()->dragSourceSystemDragEnded();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drag_source_ = new WebDragSource(browser_);
|
||||||
|
drag_source_->StartDragging(drop_data, mask, image, image_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserWebViewDelegate::runModal() {
|
void BrowserWebViewDelegate::runModal() {
|
||||||
@@ -355,6 +377,13 @@ void BrowserWebViewDelegate::HandleContextMenu(int selected_id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Private methods ------------------------------------------------------------
|
||||||
|
|
||||||
|
void BrowserWebViewDelegate::RegisterDragDrop() {
|
||||||
|
DCHECK(!drop_target_);
|
||||||
|
drop_target_ = new WebDropTarget(browser_);
|
||||||
|
}
|
||||||
|
|
||||||
// Protected methods ----------------------------------------------------------
|
// Protected methods ----------------------------------------------------------
|
||||||
|
|
||||||
void BrowserWebViewDelegate::ShowJavaScriptAlert(
|
void BrowserWebViewDelegate::ShowJavaScriptAlert(
|
||||||
|
@@ -1021,9 +1021,6 @@ int CefV8ValueImpl::AdjustExternallyAllocatedMemory(int change_in_bytes) {
|
|||||||
if (counter == NULL)
|
if (counter == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
|
||||||
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
|
||||||
|
|
||||||
int new_value = *counter + change_in_bytes;
|
int new_value = *counter + change_in_bytes;
|
||||||
if (new_value < 0) {
|
if (new_value < 0) {
|
||||||
NOTREACHED() << "External memory usage cannot be less than 0 bytes";
|
NOTREACHED() << "External memory usage cannot be less than 0 bytes";
|
||||||
|
159
libcef/web_drag_source_gtk.cc
Normal file
159
libcef/web_drag_source_gtk.cc
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2011 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 "libcef/web_drag_source_gtk.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "libcef/browser_impl.h"
|
||||||
|
#include "libcef/cef_context.h"
|
||||||
|
#include "libcef/drag_data_impl.h"
|
||||||
|
#include "libcef/web_drop_target_gtk.h"
|
||||||
|
|
||||||
|
#include "base/utf_string_conversions.h"
|
||||||
|
#include "googleurl/src/gurl.h"
|
||||||
|
#include "net/base/net_util.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebDragData.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPoint.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebImage.h"
|
||||||
|
#include "ui/base/dragdrop/os_exchange_data.h"
|
||||||
|
#include "ui/base/dragdrop/os_exchange_data_provider_gtk.h"
|
||||||
|
#include "ui/base/dragdrop/drag_drop_types.h"
|
||||||
|
#include "ui/base/dragdrop/gtk_dnd_util.h"
|
||||||
|
#include "ui/gfx/gtk_util.h"
|
||||||
|
#include "webkit/glue/webdropdata.h"
|
||||||
|
#include "webkit/glue/window_open_disposition.h"
|
||||||
|
|
||||||
|
|
||||||
|
using WebKit::WebDragOperation;
|
||||||
|
using WebKit::WebDragOperationNone;
|
||||||
|
using WebKit::WebDragOperationCopy;
|
||||||
|
using WebKit::WebDragOperationLink;
|
||||||
|
using WebKit::WebDragOperationMove;
|
||||||
|
using WebKit::WebDragOperationGeneric;
|
||||||
|
using WebKit::WebPoint;
|
||||||
|
using WebKit::WebView;
|
||||||
|
using WebKit::WebDragOperationsMask;
|
||||||
|
using ui::DragDropTypes;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void drag_end(GtkWidget* widget, GdkDragContext* context,
|
||||||
|
WebDragSource* user_data) {
|
||||||
|
user_data->OnDragEnd(widget, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool drag_failed(GtkWidget* widget, GdkDragContext* context,
|
||||||
|
GtkDragResult result, WebDragSource* user_data) {
|
||||||
|
return user_data->OnDragFailed(widget, context, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drag_data_get(GtkWidget* widget, GdkDragContext* context,
|
||||||
|
GtkSelectionData* selection_data, guint target_type,
|
||||||
|
guint time, WebDragSource* user_data) {
|
||||||
|
user_data->OnDragDataGet(widget, context, selection_data, target_type, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
WebDragSource::WebDragSource(CefBrowserImpl* browser)
|
||||||
|
: browser_(browser) {
|
||||||
|
widget_ = gtk_invisible_new();
|
||||||
|
// At some point we might want to listen to drag-begin
|
||||||
|
g_signal_connect(widget_, "drag-end", G_CALLBACK(&drag_end), this);
|
||||||
|
g_signal_connect(widget_, "drag-failed", G_CALLBACK(&drag_failed), this);
|
||||||
|
g_signal_connect(widget_, "drag-data-get", G_CALLBACK(&drag_data_get), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebDragSource::~WebDragSource() {
|
||||||
|
gtk_widget_destroy(widget_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebDragSource::StartDragging(const WebDropData& drop_data,
|
||||||
|
WebDragOperationsMask mask,
|
||||||
|
const WebKit::WebImage& image,
|
||||||
|
const WebKit::WebPoint& image_offset) {
|
||||||
|
drop_data_.reset(new WebDropData(drop_data));
|
||||||
|
int targets_mask = 0;
|
||||||
|
if (!drop_data.plain_text.empty())
|
||||||
|
targets_mask |= ui::TEXT_PLAIN;
|
||||||
|
if (drop_data.url.is_valid()) {
|
||||||
|
targets_mask |= ui::TEXT_URI_LIST;
|
||||||
|
targets_mask |= ui::CHROME_NAMED_URL;
|
||||||
|
targets_mask |= ui::NETSCAPE_URL;
|
||||||
|
}
|
||||||
|
if (!drop_data.text_html.empty())
|
||||||
|
targets_mask |= ui::TEXT_HTML;
|
||||||
|
GtkTargetList* tl = ui::GetTargetListFromCodeMask(targets_mask);
|
||||||
|
|
||||||
|
GdkEvent* event = gtk_get_current_event();
|
||||||
|
GdkDragContext* context = gtk_drag_begin(widget_, tl,
|
||||||
|
(GdkDragAction)DragDropTypes::DragOperationToGdkDragAction(mask), 1,
|
||||||
|
event);
|
||||||
|
if (!image.isNull()) {
|
||||||
|
const SkBitmap& bitmap = image.getSkBitmap();
|
||||||
|
GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(&bitmap);
|
||||||
|
gtk_drag_set_icon_pixbuf(context, pixbuf, image_offset.x, image_offset.y);
|
||||||
|
gdk_pixbuf_unref(pixbuf);
|
||||||
|
} else {
|
||||||
|
gtk_drag_set_icon_default(context);
|
||||||
|
}
|
||||||
|
gdk_event_free(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebDragSource::OnDragEnd(GtkWidget* widget, GdkDragContext* context) {
|
||||||
|
gfx::Point client(0, 0);
|
||||||
|
gfx::Point screen(0, 0);
|
||||||
|
getView()->dragSourceEndedAt(client, screen, WebDragOperationNone);
|
||||||
|
getView()->dragSourceSystemDragEnded();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebDragSource::OnDragFailed(GtkWidget* widget, GdkDragContext* context,
|
||||||
|
GtkDragResult result) {
|
||||||
|
gfx::Point client(0, 0);
|
||||||
|
gfx::Point screen(0, 0);
|
||||||
|
getView()->dragSourceEndedAt(client, screen, WebDragOperationNone);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebDragSource::OnDragDataGet(GtkWidget* sender, GdkDragContext* context,
|
||||||
|
GtkSelectionData* selection_data,
|
||||||
|
guint target_type, guint time) {
|
||||||
|
switch (target_type) {
|
||||||
|
case ui::TEXT_PLAIN: {
|
||||||
|
std::string utf8_text = UTF16ToUTF8(drop_data_->plain_text);
|
||||||
|
gtk_selection_data_set_text(selection_data, utf8_text.c_str(),
|
||||||
|
utf8_text.length());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ui::TEXT_HTML: {
|
||||||
|
std::string utf8_text = UTF16ToUTF8(drop_data_->text_html);
|
||||||
|
gtk_selection_data_set(selection_data,
|
||||||
|
ui::GetAtomForTarget(ui::TEXT_HTML),
|
||||||
|
8,
|
||||||
|
reinterpret_cast<const guchar*>(utf8_text.c_str()),
|
||||||
|
utf8_text.length());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ui::TEXT_URI_LIST:
|
||||||
|
case ui::CHROME_NAMED_URL:
|
||||||
|
case ui::NETSCAPE_URL: {
|
||||||
|
ui::WriteURLWithName(selection_data, drop_data_->url,
|
||||||
|
drop_data_->url_title, target_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WebKit::WebView* WebDragSource::getView() {
|
||||||
|
return browser_->UIT_GetWebView();
|
||||||
|
}
|
||||||
|
|
47
libcef/web_drag_source_gtk.h
Normal file
47
libcef/web_drag_source_gtk.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2010 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.
|
||||||
|
|
||||||
|
#ifndef CEF_LIBCEF_WEB_DRAG_SOURCE_GTK_H_
|
||||||
|
#define CEF_LIBCEF_WEB_DRAG_SOURCE_GTK_H_
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include "base/memory/ref_counted.h"
|
||||||
|
#include "base/memory/scoped_ptr.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h"
|
||||||
|
|
||||||
|
class CefBrowserImpl;
|
||||||
|
class WebDropData;
|
||||||
|
|
||||||
|
namespace WebKit {
|
||||||
|
class WebImage;
|
||||||
|
class WebPoint;
|
||||||
|
class WebView;
|
||||||
|
}
|
||||||
|
|
||||||
|
class WebDragSource : public base::RefCounted<WebDragSource> {
|
||||||
|
public:
|
||||||
|
explicit WebDragSource(CefBrowserImpl* browser);
|
||||||
|
virtual ~WebDragSource();
|
||||||
|
|
||||||
|
void StartDragging(const WebDropData& drop_data,
|
||||||
|
WebKit::WebDragOperationsMask mask,
|
||||||
|
const WebKit::WebImage& image,
|
||||||
|
const WebKit::WebPoint& image_offset);
|
||||||
|
|
||||||
|
void OnDragEnd(GtkWidget* widget, GdkDragContext* context);
|
||||||
|
bool OnDragFailed(GtkWidget* widget, GdkDragContext* context,
|
||||||
|
GtkDragResult result);
|
||||||
|
void OnDragDataGet(GtkWidget* sender, GdkDragContext* context,
|
||||||
|
GtkSelectionData* selection_data, guint target_type,
|
||||||
|
guint time);
|
||||||
|
|
||||||
|
private:
|
||||||
|
WebKit::WebView* getView();
|
||||||
|
scoped_ptr<WebDropData> drop_data_;
|
||||||
|
CefBrowserImpl* browser_;
|
||||||
|
GtkWidget* widget_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_WEB_DRAG_SOURCE_GTK_H_
|
265
libcef/web_drop_target_gtk.cc
Normal file
265
libcef/web_drop_target_gtk.cc
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2011 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 "libcef/web_drop_target_gtk.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "libcef/browser_impl.h"
|
||||||
|
#include "libcef/cef_context.h"
|
||||||
|
#include "libcef/drag_data_impl.h"
|
||||||
|
|
||||||
|
#include "base/utf_string_conversions.h"
|
||||||
|
#include "base/bind.h"
|
||||||
|
#include "googleurl/src/gurl.h"
|
||||||
|
#include "net/base/net_util.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebDragData.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPoint.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
|
||||||
|
#include "ui/base/dragdrop/os_exchange_data.h"
|
||||||
|
#include "ui/base/dragdrop/os_exchange_data_provider_gtk.h"
|
||||||
|
#include "ui/base/dragdrop/drag_drop_types.h"
|
||||||
|
#include "ui/base/dragdrop/gtk_dnd_util.h"
|
||||||
|
#include "ui/base/gtk/gtk_screen_utils.h"
|
||||||
|
#include "webkit/glue/webdropdata.h"
|
||||||
|
#include "webkit/glue/window_open_disposition.h"
|
||||||
|
|
||||||
|
using WebKit::WebDragOperation;
|
||||||
|
using WebKit::WebDragOperationNone;
|
||||||
|
using WebKit::WebDragOperationCopy;
|
||||||
|
using WebKit::WebDragOperationLink;
|
||||||
|
using WebKit::WebDragOperationMove;
|
||||||
|
using WebKit::WebDragOperationGeneric;
|
||||||
|
using WebKit::WebDragOperationsMask;
|
||||||
|
using WebKit::WebPoint;
|
||||||
|
using WebKit::WebView;
|
||||||
|
using ui::DragDropTypes;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/// GTK callbacks
|
||||||
|
gboolean drag_motion(GtkWidget* widget, GdkDragContext* context, gint x,
|
||||||
|
gint y, guint time, WebDropTarget* user_data) {
|
||||||
|
return user_data->OnDragMove(widget, context, x, y, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drag_leave(GtkWidget* widget, GdkDragContext* context, guint time,
|
||||||
|
WebDropTarget* user_data) {
|
||||||
|
user_data->OnDragLeave(widget, context, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean drag_drop(GtkWidget* widget, GdkDragContext* context, gint x,
|
||||||
|
gint y, guint time, WebDropTarget* user_data) {
|
||||||
|
return user_data->OnDragDrop(widget, context, x, y, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drag_data_received(GtkWidget* widget, GdkDragContext* context,
|
||||||
|
gint x, gint y, GtkSelectionData* data, guint info,
|
||||||
|
guint time, WebDropTarget* user_data) {
|
||||||
|
user_data->OnDragDataReceived(widget, context, x, y, data, info, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
int supported_targets[] = {
|
||||||
|
ui::TEXT_PLAIN,
|
||||||
|
ui::TEXT_URI_LIST,
|
||||||
|
ui::TEXT_HTML,
|
||||||
|
ui::NETSCAPE_URL,
|
||||||
|
ui::CHROME_NAMED_URL,
|
||||||
|
ui::TEXT_PLAIN_NO_CHARSET,
|
||||||
|
};
|
||||||
|
|
||||||
|
WebDragOperationsMask _mask(GdkDragContext* context) {
|
||||||
|
GdkDragAction propsed_action = gdk_drag_context_get_suggested_action(context);
|
||||||
|
return (WebDragOperationsMask)DragDropTypes::GdkDragActionToDragOperation(
|
||||||
|
propsed_action);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
WebDropTarget::WebDropTarget(CefBrowserImpl* browser)
|
||||||
|
: browser_(browser),
|
||||||
|
data_requests_(0),
|
||||||
|
context_(NULL),
|
||||||
|
method_factory_(this) {
|
||||||
|
GtkWidget* widget = browser->UIT_GetWebViewHost()->view_handle();
|
||||||
|
gtk_drag_dest_set(widget, (GtkDestDefaults)0, NULL, 0,
|
||||||
|
static_cast<GdkDragAction>(GDK_ACTION_COPY | GDK_ACTION_LINK |
|
||||||
|
GDK_ACTION_MOVE));
|
||||||
|
g_signal_connect(widget, "drag-motion", G_CALLBACK(&drag_motion), this);
|
||||||
|
g_signal_connect(widget, "drag-leave", G_CALLBACK(&drag_leave), this);
|
||||||
|
g_signal_connect(widget, "drag-drop", G_CALLBACK(&drag_drop), this);
|
||||||
|
g_signal_connect(widget, "drag-data-received",
|
||||||
|
G_CALLBACK(&drag_data_received), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebDropTarget::~WebDropTarget() {
|
||||||
|
}
|
||||||
|
|
||||||
|
WebKit::WebView* WebDropTarget::getView() {
|
||||||
|
return browser_->UIT_GetWebView();
|
||||||
|
}
|
||||||
|
|
||||||
|
BrowserWebViewDelegate* WebDropTarget::getDelegate() {
|
||||||
|
return browser_->UIT_GetWebViewDelegate();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebDropTarget::OnDragMove(GtkWidget* widget, GdkDragContext* context,
|
||||||
|
gint x, gint y, guint time) {
|
||||||
|
WebView* webview = getView();
|
||||||
|
gint widget_x, widget_y;
|
||||||
|
WebDragOperation operation;
|
||||||
|
gtk_widget_translate_coordinates(gtk_widget_get_toplevel(widget), widget, x,
|
||||||
|
y, &widget_x, &widget_y);
|
||||||
|
|
||||||
|
// Request all the data and potentially start the DnD.
|
||||||
|
if (context_ != context) {
|
||||||
|
drop_data_.reset(new WebDropData);
|
||||||
|
data_requests_ = arraysize(supported_targets);
|
||||||
|
for (size_t i = 0; i < arraysize(supported_targets); ++i) {
|
||||||
|
gtk_drag_get_data(widget, context,
|
||||||
|
ui::GetAtomForTarget(supported_targets[i]),
|
||||||
|
time);
|
||||||
|
}
|
||||||
|
} else if (data_requests_ == 0) {
|
||||||
|
operation = webview->dragTargetDragOver(WebPoint(x, y),
|
||||||
|
WebPoint(widget_x, widget_y),
|
||||||
|
_mask(context));
|
||||||
|
gdk_drag_status(context,
|
||||||
|
(GdkDragAction)DragDropTypes::DragOperationToGdkDragAction(operation),
|
||||||
|
time);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Real DragLeave
|
||||||
|
void WebDropTarget::DragLeave() {
|
||||||
|
WebView* webview = getView();
|
||||||
|
webview->dragTargetDragLeave();
|
||||||
|
}
|
||||||
|
|
||||||
|
// GTK Sends DragDrop (immediately) after DragLeave
|
||||||
|
// So post re-post DragLeave allowing us to behave like chromium expects.
|
||||||
|
void WebDropTarget::OnDragLeave(GtkWidget* widget, GdkDragContext* context,
|
||||||
|
guint time) {
|
||||||
|
context_ = NULL;
|
||||||
|
drop_data_.reset();
|
||||||
|
MessageLoop::current()->PostTask(FROM_HERE,
|
||||||
|
base::Bind(&WebDropTarget::DragLeave, method_factory_.GetWeakPtr()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebDropTarget::OnDragDrop(GtkWidget* widget, GdkDragContext* context,
|
||||||
|
gint x, gint y, guint time) {
|
||||||
|
method_factory_.InvalidateWeakPtrs();
|
||||||
|
|
||||||
|
gint widget_x, widget_y;
|
||||||
|
gtk_widget_translate_coordinates(gtk_widget_get_toplevel(widget), widget, x,
|
||||||
|
y, &widget_x, &widget_y);
|
||||||
|
browser_->set_is_dropping(true);
|
||||||
|
|
||||||
|
if (browser_->UIT_GetWebView()) {
|
||||||
|
browser_->UIT_GetWebView()->dragTargetDrop(
|
||||||
|
WebPoint(x, y),
|
||||||
|
WebPoint(widget_x, widget_y));
|
||||||
|
}
|
||||||
|
browser_->set_is_dropping(false);
|
||||||
|
context_ = NULL;
|
||||||
|
gtk_drag_finish(context, TRUE, FALSE, time);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WebDropTarget::OnDragDataReceived(GtkWidget* widget,
|
||||||
|
GdkDragContext* context, gint x, gint y,
|
||||||
|
GtkSelectionData* data, guint info,
|
||||||
|
guint time) {
|
||||||
|
WebDragOperation operation;
|
||||||
|
data_requests_--;
|
||||||
|
|
||||||
|
// If the source can't provide us with valid data for a requested target,
|
||||||
|
// data->data will be NULL.
|
||||||
|
if (data->data && data->length > 0) {
|
||||||
|
if (data->target == ui::GetAtomForTarget(ui::TEXT_PLAIN) ||
|
||||||
|
data->target == ui::GetAtomForTarget(ui::TEXT_PLAIN_NO_CHARSET)) {
|
||||||
|
guchar* text = gtk_selection_data_get_text(data);
|
||||||
|
if (text) {
|
||||||
|
drop_data_->plain_text = UTF8ToUTF16((const char*)text);
|
||||||
|
g_free(text);
|
||||||
|
}
|
||||||
|
} else if (data->target == ui::GetAtomForTarget(ui::TEXT_URI_LIST)) {
|
||||||
|
gchar** uris = gtk_selection_data_get_uris(data);
|
||||||
|
if (uris) {
|
||||||
|
drop_data_->url = GURL();
|
||||||
|
for (gchar** uri_iter = uris; *uri_iter; uri_iter++) {
|
||||||
|
// Most file managers populate text/uri-list with file URLs when
|
||||||
|
// dragging files. To avoid exposing file system paths to web content,
|
||||||
|
// file URLs are never set as the URL content for the drop.
|
||||||
|
// TODO(estade): Can the filenames have a non-UTF8 encoding?
|
||||||
|
GURL url(*uri_iter);
|
||||||
|
FilePath file_path;
|
||||||
|
if (url.SchemeIs("file") &&
|
||||||
|
net::FileURLToFilePath(url, &file_path)) {
|
||||||
|
drop_data_->filenames.push_back(UTF8ToUTF16(file_path.value()));
|
||||||
|
// This is a hack. Some file managers also populate text/plain with
|
||||||
|
// a file URL when dragging files, so we clear it to avoid exposing
|
||||||
|
// it to the web content.
|
||||||
|
// drop_data_->plain_text.clear();
|
||||||
|
} else if (!drop_data_->url.is_valid()) {
|
||||||
|
// Also set the first non-file URL as the URL content for the drop.
|
||||||
|
drop_data_->url = url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_strfreev(uris);
|
||||||
|
}
|
||||||
|
} else if (data->target == ui::GetAtomForTarget(ui::TEXT_HTML)) {
|
||||||
|
drop_data_->text_html =
|
||||||
|
UTF8ToUTF16(std::string(reinterpret_cast<char*>(data->data),
|
||||||
|
data->length));
|
||||||
|
// We leave the base URL empty.
|
||||||
|
} else if (data->target == ui::GetAtomForTarget(ui::NETSCAPE_URL)) {
|
||||||
|
std::string netscape_url(reinterpret_cast<char*>(data->data),
|
||||||
|
data->length);
|
||||||
|
size_t split = netscape_url.find_first_of('\n');
|
||||||
|
if (split != std::string::npos) {
|
||||||
|
drop_data_->url = GURL(netscape_url.substr(0, split));
|
||||||
|
if (split < netscape_url.size() - 1)
|
||||||
|
drop_data_->url_title = UTF8ToUTF16(netscape_url.substr(split + 1));
|
||||||
|
}
|
||||||
|
} else if (data->target == ui::GetAtomForTarget(ui::CHROME_NAMED_URL)) {
|
||||||
|
ui::ExtractNamedURL(data, &drop_data_->url, &drop_data_->url_title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_requests_ == 0) {
|
||||||
|
CefRefPtr<CefClient> client = browser_->GetClient();
|
||||||
|
if (client.get()) {
|
||||||
|
CefRefPtr<CefDragHandler> handler = client->GetDragHandler();
|
||||||
|
if (handler.get()) {
|
||||||
|
CefRefPtr<CefDragData> data(new CefDragDataImpl(*drop_data_.get()));
|
||||||
|
if (handler->OnDragEnter(browser_, data,
|
||||||
|
(cef_drag_operations_mask_t)_mask(context))) {
|
||||||
|
operation = WebDragOperationNone;
|
||||||
|
gdk_drag_status(context,
|
||||||
|
(GdkDragAction)DragDropTypes::DragOperationToGdkDragAction(
|
||||||
|
operation),
|
||||||
|
time);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gint widget_x, widget_y;
|
||||||
|
gtk_widget_translate_coordinates(gtk_widget_get_toplevel(widget), widget,
|
||||||
|
x, y, &widget_x, &widget_y);
|
||||||
|
WebView* webview = getView();
|
||||||
|
operation = webview->dragTargetDragEnter(drop_data_->ToDragData(),
|
||||||
|
WebPoint(x, y),
|
||||||
|
WebPoint(widget_x, widget_y),
|
||||||
|
_mask(context));
|
||||||
|
gdk_drag_status(context,
|
||||||
|
(GdkDragAction)DragDropTypes::DragOperationToGdkDragAction(operation),
|
||||||
|
time);
|
||||||
|
context_ = context;
|
||||||
|
}
|
||||||
|
}
|
52
libcef/web_drop_target_gtk.h
Normal file
52
libcef/web_drop_target_gtk.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2010 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.
|
||||||
|
|
||||||
|
#ifndef CEF_LIBCEF_WEB_DROP_TARGET_GTK_H_
|
||||||
|
#define CEF_LIBCEF_WEB_DROP_TARGET_GTK_H_
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include "base/memory/ref_counted.h"
|
||||||
|
#include "base/memory/scoped_ptr.h"
|
||||||
|
#include "base/memory/weak_ptr.h"
|
||||||
|
|
||||||
|
class BrowserWebViewDelegate;
|
||||||
|
class CefBrowserImpl;
|
||||||
|
class WebDropData;
|
||||||
|
|
||||||
|
namespace WebKit {
|
||||||
|
class WebView;
|
||||||
|
}
|
||||||
|
|
||||||
|
class WebDropTarget : public base::RefCounted<WebDropTarget> {
|
||||||
|
public:
|
||||||
|
explicit WebDropTarget(CefBrowserImpl* browser);
|
||||||
|
virtual ~WebDropTarget();
|
||||||
|
|
||||||
|
WebKit::WebView* getView();
|
||||||
|
BrowserWebViewDelegate* getDelegate();
|
||||||
|
|
||||||
|
// Called by GTK callbacks
|
||||||
|
bool OnDragMove(GtkWidget* widget, GdkDragContext* context, gint x, gint y,
|
||||||
|
guint time);
|
||||||
|
void OnDragLeave(GtkWidget* widget, GdkDragContext* context, guint time);
|
||||||
|
bool OnDragDrop(GtkWidget* widget, GdkDragContext* context, gint x, gint y,
|
||||||
|
guint time);
|
||||||
|
void OnDragEnd(GtkWidget* widget, GdkDragContext* context, guint time);
|
||||||
|
void OnDragDataReceived(GtkWidget* widget, GdkDragContext* context, gint x,
|
||||||
|
gint y, GtkSelectionData* data, guint info,
|
||||||
|
guint time);
|
||||||
|
void DragLeave();
|
||||||
|
|
||||||
|
private:
|
||||||
|
CefBrowserImpl* browser_;
|
||||||
|
scoped_ptr<WebDropData> drop_data_;
|
||||||
|
bool entered_;
|
||||||
|
int data_requests_;
|
||||||
|
GdkDragContext* context_;
|
||||||
|
base::WeakPtrFactory<WebDropTarget> method_factory_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_WEB_DROP_TARGET_GTK_H_
|
||||||
|
|
@@ -27,8 +27,7 @@ void destroy(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TerminationSignalHandler(int signatl) {
|
void TerminationSignalHandler(int signatl) {
|
||||||
CefShutdown();
|
destroy();
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callback for Debug > Get Source... menu item.
|
// Callback for Debug > Get Source... menu item.
|
||||||
|
Reference in New Issue
Block a user