mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
- Add CefDragHandler to support examination of drag data and cancellation of drag requests (issue #297).
- Mac: Fix dragging of URLs by providing a default image if no drag image is supplied. git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@279 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
@@ -15,6 +15,10 @@ class WebFrame;
|
||||
class WebView;
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
class FilePath;
|
||||
#endif
|
||||
|
||||
namespace webkit_glue {
|
||||
|
||||
#if defined(OS_WIN)
|
||||
@@ -28,6 +32,7 @@ BOOL SaveBitmapToFile(HBITMAP hBmp, HDC hDC, LPCTSTR file, LPBYTE lpBits);
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
void InitializeDataPak();
|
||||
FilePath GetResourcesFilePath();
|
||||
#endif
|
||||
|
||||
// Text encoding objects must be initialized on the main thread.
|
||||
|
@@ -5,6 +5,7 @@
|
||||
#include "browser_webview_delegate.h"
|
||||
#import "browser_webview_mac.h"
|
||||
#include "browser_impl.h"
|
||||
#include "drag_data_impl.h"
|
||||
#import "include/cef_application_mac.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
@@ -138,6 +139,21 @@ void BrowserWebViewDelegate::startDragging(const WebDragData& data,
|
||||
if (!view)
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// By allowing nested tasks, the code below also allows Close(),
|
||||
// which would deallocate |this|. The same problem can occur while
|
||||
// processing -sendEvent:, so Close() is deferred in that case.
|
||||
@@ -148,13 +164,16 @@ void BrowserWebViewDelegate::startDragging(const WebDragData& data,
|
||||
// The drag invokes a nested event loop, arrange to continue
|
||||
// processing events.
|
||||
MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
|
||||
NSDragOperation op_mask = static_cast<NSDragOperation>(mask);
|
||||
const SkBitmap& bitmap = gfx::CGImageToSkBitmap(image.getCGImageRef());
|
||||
CGColorSpaceRef color_space = base::mac::GetSystemColorSpace();
|
||||
NSImage* ns_image = gfx::SkBitmapToNSImageWithColorSpace(bitmap, color_space);
|
||||
|
||||
NSImage* ns_image = nil;
|
||||
if (!image.isNull()) {
|
||||
const SkBitmap& bitmap = gfx::CGImageToSkBitmap(image.getCGImageRef());
|
||||
CGColorSpaceRef color_space = base::mac::GetSystemColorSpace();
|
||||
ns_image = gfx::SkBitmapToNSImageWithColorSpace(bitmap, color_space);
|
||||
}
|
||||
NSPoint offset = NSPointFromCGPoint(gfx::Point(image_offset).ToCGPoint());
|
||||
[view startDragWithDropData:WebDropData(data)
|
||||
dragOperationMask:op_mask
|
||||
[view startDragWithDropData:drop_data
|
||||
dragOperationMask:static_cast<NSDragOperation>(mask)
|
||||
image:ns_image
|
||||
offset:offset];
|
||||
}
|
||||
|
@@ -12,6 +12,7 @@
|
||||
#include "browser_impl.h"
|
||||
#include "browser_webview_delegate.h"
|
||||
#include "cef_context.h"
|
||||
#include "drag_data_impl.h"
|
||||
#include "web_drop_target_win.h"
|
||||
|
||||
#include <objidl.h>
|
||||
@@ -190,8 +191,23 @@ void BrowserWebViewDelegate::startDragging(
|
||||
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))) {
|
||||
EndDragging();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drag_delegate_ = new BrowserDragDelegate(this);
|
||||
drag_delegate_->StartDragging(WebDropData(data), mask, image.getSkBitmap(),
|
||||
drag_delegate_->StartDragging(drop_data, mask, image.getSkBitmap(),
|
||||
image_offset);
|
||||
}
|
||||
|
||||
@@ -563,8 +579,7 @@ end:
|
||||
|
||||
void BrowserWebViewDelegate::RegisterDragDrop() {
|
||||
DCHECK(!drop_target_);
|
||||
drop_target_ = new WebDropTarget(browser_->UIT_GetWebViewWndHandle(),
|
||||
browser_->UIT_GetWebView());
|
||||
drop_target_ = new WebDropTarget(browser_);
|
||||
}
|
||||
|
||||
void BrowserWebViewDelegate::RevokeDragDrop() {
|
||||
|
78
libcef/drag_data_impl.cc
Normal file
78
libcef/drag_data_impl.cc
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright (c) 2011 The Chromium Embedded Framework 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 "drag_data_impl.h"
|
||||
|
||||
CefDragDataImpl::CefDragDataImpl(const WebDropData& data)
|
||||
: data_(data)
|
||||
{
|
||||
}
|
||||
|
||||
bool CefDragDataImpl::IsLink()
|
||||
{
|
||||
return (data_.url.is_valid() && data_.file_extension.empty());
|
||||
}
|
||||
|
||||
bool CefDragDataImpl::IsFragment()
|
||||
{
|
||||
return (!data_.url.is_valid() && data_.file_extension.empty() &&
|
||||
data_.filenames.empty());
|
||||
}
|
||||
|
||||
bool CefDragDataImpl::IsFile()
|
||||
{
|
||||
return (!data_.file_extension.empty() || !data_.filenames.empty());
|
||||
}
|
||||
|
||||
CefString CefDragDataImpl::GetLinkURL()
|
||||
{
|
||||
return data_.url.spec();
|
||||
}
|
||||
|
||||
CefString CefDragDataImpl::GetLinkTitle()
|
||||
{
|
||||
return data_.url_title;
|
||||
}
|
||||
|
||||
CefString CefDragDataImpl::GetLinkMetadata()
|
||||
{
|
||||
return data_.download_metadata;
|
||||
}
|
||||
|
||||
CefString CefDragDataImpl::GetFragmentText()
|
||||
{
|
||||
return data_.plain_text;
|
||||
}
|
||||
|
||||
CefString CefDragDataImpl::GetFragmentHtml()
|
||||
{
|
||||
return data_.text_html;
|
||||
}
|
||||
|
||||
CefString CefDragDataImpl::GetFragmentBaseURL()
|
||||
{
|
||||
return data_.html_base_url.spec();
|
||||
}
|
||||
|
||||
CefString CefDragDataImpl::GetFileExtension()
|
||||
{
|
||||
return data_.file_extension;
|
||||
}
|
||||
|
||||
CefString CefDragDataImpl::GetFileName()
|
||||
{
|
||||
return data_.file_description_filename;
|
||||
}
|
||||
|
||||
bool CefDragDataImpl::GetFileNames(std::vector<CefString>& names)
|
||||
{
|
||||
if (data_.filenames.empty())
|
||||
return false;
|
||||
|
||||
std::vector<string16>::const_iterator it = data_.filenames.begin();
|
||||
for (; it != data_.filenames.end(); ++it)
|
||||
names.push_back(*it);
|
||||
|
||||
return true;
|
||||
}
|
36
libcef/drag_data_impl.h
Normal file
36
libcef/drag_data_impl.h
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2011 The Chromium Embedded Framework 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 _DRAG_DATA_IMPL_H
|
||||
#define _DRAG_DATA_IMPL_H
|
||||
|
||||
#include "../include/cef.h"
|
||||
#include "webkit/glue/webdropdata.h"
|
||||
|
||||
// Implementation of CefDragData.
|
||||
class CefDragDataImpl : public CefDragData
|
||||
{
|
||||
public:
|
||||
explicit CefDragDataImpl(const WebDropData& data);
|
||||
|
||||
virtual bool IsLink();
|
||||
virtual bool IsFragment();
|
||||
virtual bool IsFile();
|
||||
virtual CefString GetLinkURL();
|
||||
virtual CefString GetLinkTitle();
|
||||
virtual CefString GetLinkMetadata();
|
||||
virtual CefString GetFragmentText();
|
||||
virtual CefString GetFragmentHtml();
|
||||
virtual CefString GetFragmentBaseURL();
|
||||
virtual CefString GetFileExtension();
|
||||
virtual CefString GetFileName();
|
||||
virtual bool GetFileNames(std::vector<CefString>& names);
|
||||
|
||||
protected:
|
||||
WebDropData data_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(CefDragDataImpl);
|
||||
};
|
||||
|
||||
#endif // _DRAG_DATA_IMPL_H
|
@@ -4,6 +4,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "browser_impl.h"
|
||||
#include "browser_webkit_glue.h"
|
||||
#import "browser_webview_mac.h"
|
||||
#include "drag_download_util.h"
|
||||
#include "download_util.h"
|
||||
@@ -140,6 +141,14 @@ void PromiseWriterTask::Run() {
|
||||
dropData_.reset(new WebDropData(*dropData));
|
||||
DCHECK(dropData_.get());
|
||||
|
||||
if (image == nil) {
|
||||
// No drag image was provided so create one.
|
||||
FilePath path = webkit_glue::GetResourcesFilePath();
|
||||
path = path.AppendASCII("urlIcon.png");
|
||||
image = [[NSImage alloc]
|
||||
initWithContentsOfFile:SysUTF8ToNSString(path.value())];
|
||||
}
|
||||
|
||||
dragImage_.reset([image retain]);
|
||||
imageOffset_ = offset;
|
||||
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include "browser_impl.h"
|
||||
#import "browser_webview_mac.h"
|
||||
#include "cef_context.h"
|
||||
#include "drag_data_impl.h"
|
||||
#import "web_drop_target_mac.h"
|
||||
#import "web_drag_utils_mac.h"
|
||||
|
||||
@@ -30,8 +31,10 @@ using WebKit::WebView;
|
||||
// drag&drop messages to WebCore and handle navigation on a successful drop
|
||||
// (if necessary).
|
||||
- (id)initWithWebView:(BrowserWebView*)view {
|
||||
if ((self = [super init]))
|
||||
if ((self = [super init])) {
|
||||
view_ = view;
|
||||
canceled_ = false;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -86,17 +89,34 @@ using WebKit::WebView;
|
||||
WebView* webview = view_.browser->UIT_GetWebView();
|
||||
|
||||
// Fill out a WebDropData from pasteboard.
|
||||
WebDropData data;
|
||||
[self populateWebDropData:&data fromPasteboard:[info draggingPasteboard]];
|
||||
WebDropData drop_data;
|
||||
[self populateWebDropData:&drop_data
|
||||
fromPasteboard:[info draggingPasteboard]];
|
||||
|
||||
NSDragOperation mask = [info draggingSourceOperationMask];
|
||||
|
||||
canceled_ = false;
|
||||
|
||||
CefRefPtr<CefClient> client = view_.browser->GetClient();
|
||||
if (client.get()) {
|
||||
CefRefPtr<CefDragHandler> handler = client->GetDragHandler();
|
||||
if (handler.get()) {
|
||||
CefRefPtr<CefDragData> data(new CefDragDataImpl(drop_data));
|
||||
if (handler->OnDragEnter(view_.browser, data,
|
||||
static_cast<CefDragHandler::DragOperationsMask>(mask))) {
|
||||
canceled_ = true;
|
||||
return NSDragOperationNone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create the appropriate mouse locations for WebCore. The draggingLocation
|
||||
// is in window coordinates. Both need to be flipped.
|
||||
NSPoint windowPoint = [info draggingLocation];
|
||||
NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
|
||||
NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
|
||||
NSDragOperation mask = [info draggingSourceOperationMask];
|
||||
WebDragOperation op =
|
||||
webview->dragTargetDragEnter(data.ToDragData(),
|
||||
webview->dragTargetDragEnter(drop_data.ToDragData(),
|
||||
WebPoint(viewPoint.x, viewPoint.y),
|
||||
WebPoint(screenPoint.x, screenPoint.y),
|
||||
static_cast<WebDragOperationsMask>(mask));
|
||||
@@ -108,6 +128,9 @@ using WebKit::WebView;
|
||||
if (current_wvh_ != _Context->current_webviewhost())
|
||||
return;
|
||||
|
||||
if (canceled_)
|
||||
return;
|
||||
|
||||
WebView* webview = view_.browser->UIT_GetWebView();
|
||||
|
||||
// Nothing to do in the interstitial case.
|
||||
@@ -127,6 +150,9 @@ using WebKit::WebView;
|
||||
return NSDragOperationNone;
|
||||
}
|
||||
|
||||
if (canceled_)
|
||||
return NSDragOperationNone;
|
||||
|
||||
WebView* webview = view_.browser->UIT_GetWebView();
|
||||
|
||||
// Create the appropriate mouse locations for WebCore. The draggingLocation
|
||||
|
@@ -3,9 +3,11 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "web_drop_target_win.h"
|
||||
#include "browser_impl.h"
|
||||
#include "cef_context.h"
|
||||
#include "drag_data_impl.h"
|
||||
#include "web_drag_utils_win.h"
|
||||
#include "web_drop_target_win.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <shlobj.h>
|
||||
@@ -28,6 +30,7 @@ using WebKit::WebDragOperationLink;
|
||||
using WebKit::WebDragOperationMove;
|
||||
using WebKit::WebDragOperationGeneric;
|
||||
using WebKit::WebPoint;
|
||||
using WebKit::WebView;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -44,11 +47,12 @@ DWORD GetPreferredDropEffect(DWORD effect) {
|
||||
|
||||
} // namespace
|
||||
|
||||
WebDropTarget::WebDropTarget(HWND source_hwnd, WebKit::WebView* view)
|
||||
: ui::DropTarget(source_hwnd),
|
||||
view_(view),
|
||||
WebDropTarget::WebDropTarget(CefBrowserImpl* browser)
|
||||
: ui::DropTarget(browser->UIT_GetWebViewWndHandle()),
|
||||
browser_(browser),
|
||||
current_wvh_(NULL),
|
||||
drag_cursor_(WebDragOperationNone) {
|
||||
drag_cursor_(WebDragOperationNone),
|
||||
canceled_(false) {
|
||||
}
|
||||
|
||||
WebDropTarget::~WebDropTarget() {
|
||||
@@ -69,15 +73,33 @@ DWORD WebDropTarget::OnDragEnter(IDataObject* data_object,
|
||||
if (drop_data.url.is_empty())
|
||||
ui::OSExchangeDataProviderWin::GetPlainTextURL(data_object, &drop_data.url);
|
||||
|
||||
WebKit::WebDragOperationsMask mask =
|
||||
web_drag_utils_win::WinDragOpMaskToWebDragOpMask(effects);
|
||||
|
||||
canceled_ = false;
|
||||
|
||||
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->OnDragEnter(browser_, data,
|
||||
static_cast<CefDragHandler::DragOperationsMask>(mask))) {
|
||||
canceled_ = true;
|
||||
return DROPEFFECT_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drag_cursor_ = WebDragOperationNone;
|
||||
|
||||
POINT client_pt = cursor_position;
|
||||
ScreenToClient(GetHWND(), &client_pt);
|
||||
WebDragOperation operation = view_->dragTargetDragEnter(
|
||||
WebDragOperation operation = browser_->UIT_GetWebView()->dragTargetDragEnter(
|
||||
drop_data.ToDragData(),
|
||||
WebPoint(client_pt.x, client_pt.y),
|
||||
WebPoint(cursor_position.x, cursor_position.y),
|
||||
web_drag_utils_win::WinDragOpMaskToWebDragOpMask(effects));
|
||||
mask);
|
||||
|
||||
return web_drag_utils_win::WebDragOpToWinDragOp(operation);
|
||||
}
|
||||
@@ -90,9 +112,12 @@ DWORD WebDropTarget::OnDragOver(IDataObject* data_object,
|
||||
if (current_wvh_ != _Context->current_webviewhost())
|
||||
OnDragEnter(data_object, key_state, cursor_position, effects);
|
||||
|
||||
if (canceled_)
|
||||
return DROPEFFECT_NONE;
|
||||
|
||||
POINT client_pt = cursor_position;
|
||||
ScreenToClient(GetHWND(), &client_pt);
|
||||
WebDragOperation operation = view_->dragTargetDragOver(
|
||||
WebDragOperation operation = browser_->UIT_GetWebView()->dragTargetDragOver(
|
||||
WebPoint(client_pt.x, client_pt.y),
|
||||
WebPoint(cursor_position.x, cursor_position.y),
|
||||
web_drag_utils_win::WinDragOpMaskToWebDragOpMask(effects));
|
||||
@@ -105,7 +130,10 @@ void WebDropTarget::OnDragLeave(IDataObject* data_object) {
|
||||
if (current_wvh_ != _Context->current_webviewhost())
|
||||
return;
|
||||
|
||||
view_->dragTargetDragLeave();
|
||||
if (canceled_)
|
||||
return;
|
||||
|
||||
browser_->UIT_GetWebView()->dragTargetDragLeave();
|
||||
}
|
||||
|
||||
DWORD WebDropTarget::OnDrop(IDataObject* data_object,
|
||||
@@ -118,7 +146,7 @@ DWORD WebDropTarget::OnDrop(IDataObject* data_object,
|
||||
|
||||
POINT client_pt = cursor_position;
|
||||
ScreenToClient(GetHWND(), &client_pt);
|
||||
view_->dragTargetDrop(
|
||||
browser_->UIT_GetWebView()->dragTargetDrop(
|
||||
WebPoint(client_pt.x, client_pt.y),
|
||||
WebPoint(cursor_position.x, cursor_position.y));
|
||||
|
||||
|
@@ -11,9 +11,7 @@
|
||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h"
|
||||
#include "ui/base/dragdrop/drop_target.h"
|
||||
|
||||
namespace WebKit {
|
||||
class WebView;
|
||||
};
|
||||
class CefBrowserImpl;
|
||||
class WebViewHost;
|
||||
|
||||
// A helper object that provides drop capabilities to a WebView. The
|
||||
@@ -23,7 +21,7 @@ class WebDropTarget : public ui::DropTarget {
|
||||
public:
|
||||
// Create a new WebDropTarget associating it with the given HWND and
|
||||
// WebView.
|
||||
WebDropTarget(HWND source_hwnd, WebKit::WebView* view);
|
||||
WebDropTarget(CefBrowserImpl* browser);
|
||||
virtual ~WebDropTarget();
|
||||
|
||||
void set_drag_cursor(WebKit::WebDragOperation op) {
|
||||
@@ -49,8 +47,8 @@ class WebDropTarget : public ui::DropTarget {
|
||||
DWORD effect);
|
||||
|
||||
private:
|
||||
// Our associated WebView.
|
||||
WebKit::WebView* view_;
|
||||
// Our associated CefBrowserImpl.
|
||||
CefBrowserImpl* browser_;
|
||||
|
||||
// We keep track of the web view host we're dragging over. If it changes
|
||||
// during a drag, we need to re-send the DragEnter message. WARNING:
|
||||
@@ -62,6 +60,9 @@ class WebDropTarget : public ui::DropTarget {
|
||||
// content area. This can be updated async during a drag operation.
|
||||
WebKit::WebDragOperation drag_cursor_;
|
||||
|
||||
// True if the drag has been canceled.
|
||||
bool canceled_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WebDropTarget);
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user