Add off-screen drag & drop support (issue #1032).

git-svn-id: https://chromiumembedded.googlecode.com/svn/branches/1916@1707 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2014-05-22 16:11:26 +00:00
parent dceb7fcaa3
commit 998fa796ca
35 changed files with 3061 additions and 40 deletions

View File

@ -104,6 +104,8 @@
'tests/cefclient/cefclient.h',
'tests/cefclient/binding_test.cpp',
'tests/cefclient/binding_test.h',
'tests/cefclient/bytes_write_handler.cpp',
'tests/cefclient/bytes_write_handler.h',
'tests/cefclient/client_app.cpp',
'tests/cefclient/client_app.h',
'tests/cefclient/client_app_delegates.cpp',
@ -117,6 +119,7 @@
'tests/cefclient/dialog_test.h',
'tests/cefclient/dom_test.cpp',
'tests/cefclient/dom_test.h',
'tests/cefclient/dragdrop_events.h',
'tests/cefclient/osrenderer.h',
'tests/cefclient/osrenderer.cpp',
'tests/cefclient/performance_test.cpp',
@ -136,6 +139,8 @@
'cefclient_sources_win': [
'tests/cefclient/cefclient.exe.manifest',
'tests/cefclient/cefclient.rc',
'tests/cefclient/cefclient_osr_dragdrop_win.h',
'tests/cefclient/cefclient_osr_dragdrop_win.cpp',
'tests/cefclient/cefclient_osr_widget_win.h',
'tests/cefclient/cefclient_osr_widget_win.cpp',
'tests/cefclient/cefclient_win.cpp',

View File

@ -39,6 +39,7 @@
#pragma once
#include "include/capi/cef_base_capi.h"
#include "include/capi/cef_drag_data_capi.h"
#include "include/capi/cef_frame_capi.h"
#include "include/capi/cef_process_message_capi.h"
#include "include/capi/cef_request_context_capi.h"
@ -453,6 +454,70 @@ typedef struct _cef_browser_host_t {
///
void (CEF_CALLBACK *handle_key_event_after_text_input_client)(
struct _cef_browser_host_t* self, cef_event_handle_t keyEvent);
///
// Call this function when the user drags the mouse into the web view (before
// calling DragTargetDragOver/DragTargetLeave/DragTargetDrop). |drag_data|
// should not contain file contents as this type of data is not allowed to be
// dragged into the web view. File contents can be removed using
// cef_drag_data_t::ResetFileContents (for example, if |drag_data| comes from
// cef_render_handler_t::StartDragging). This function is only used when
// window rendering is disabled.
///
void (CEF_CALLBACK *drag_target_drag_enter)(struct _cef_browser_host_t* self,
struct _cef_drag_data_t* drag_data,
const struct _cef_mouse_event_t* event,
cef_drag_operations_mask_t allowed_ops);
///
// Call this function each time the mouse is moved across the web view during
// a drag operation (after calling DragTargetDragEnter and before calling
// DragTargetDragLeave/DragTargetDrop). This function is only used when window
// rendering is disabled.
///
void (CEF_CALLBACK *drag_target_drag_over)(struct _cef_browser_host_t* self,
const struct _cef_mouse_event_t* event,
cef_drag_operations_mask_t allowed_ops);
///
// Call this function when the user drags the mouse out of the web view (after
// calling DragTargetDragEnter). This function is only used when window
// rendering is disabled.
///
void (CEF_CALLBACK *drag_target_drag_leave)(struct _cef_browser_host_t* self);
///
// Call this function when the user completes the drag operation by dropping
// the object onto the web view (after calling DragTargetDragEnter). The
// object being dropped is |drag_data|, given as an argument to the previous
// DragTargetDragEnter call. This function is only used when window rendering
// is disabled.
///
void (CEF_CALLBACK *drag_target_drop)(struct _cef_browser_host_t* self,
const struct _cef_mouse_event_t* event);
///
// Call this function when the drag operation started by a
// cef_render_handler_t::StartDragging call has ended either in a drop or by
// being cancelled. |x| and |y| are mouse coordinates relative to the upper-
// left corner of the view. If the web view is both the drag source and the
// drag target then all DragTarget* functions should be called before
// DragSource* mthods. This function is only used when window rendering is
// disabled.
///
void (CEF_CALLBACK *drag_source_ended_at)(struct _cef_browser_host_t* self,
int x, int y, cef_drag_operations_mask_t op);
///
// Call this function when the drag operation started by a
// cef_render_handler_t::StartDragging call has completed. This function may
// be called immediately without first calling DragSourceEndedAt to cancel a
// drag operation. If the web view is both the drag source and the drag target
// then all DragTarget* functions should be called before DragSource* mthods.
// This function is only used when window rendering is disabled.
///
void (CEF_CALLBACK *drag_source_system_drag_ended)(
struct _cef_browser_host_t* self);
} cef_browser_host_t;

View File

@ -39,6 +39,7 @@
#pragma once
#include "include/capi/cef_base_capi.h"
#include "include/capi/cef_stream_capi.h"
#ifdef __cplusplus
extern "C" {
@ -55,6 +56,16 @@ typedef struct _cef_drag_data_t {
///
cef_base_t base;
///
// Returns a copy of the current object.
///
struct _cef_drag_data_t* (CEF_CALLBACK *clone)(struct _cef_drag_data_t* self);
///
// Returns true (1) if this object is read-only.
///
int (CEF_CALLBACK *is_read_only)(struct _cef_drag_data_t* self);
///
// Returns true (1) if the drag data is a link.
///
@ -120,15 +131,79 @@ typedef struct _cef_drag_data_t {
cef_string_userfree_t (CEF_CALLBACK *get_file_name)(
struct _cef_drag_data_t* self);
///
// Write the contents of the file being dragged out of the web view into
// |writer|. Returns the number of bytes sent to |writer|. If |writer| is NULL
// this function will return the size of the file contents in bytes. Call
// get_file_name() to get a suggested name for the file.
///
size_t (CEF_CALLBACK *get_file_contents)(struct _cef_drag_data_t* self,
struct _cef_stream_writer_t* writer);
///
// Retrieve the list of file names that are being dragged into the browser
// window.
///
int (CEF_CALLBACK *get_file_names)(struct _cef_drag_data_t* self,
cef_string_list_t names);
///
// Set the link URL that is being dragged.
///
void (CEF_CALLBACK *set_link_url)(struct _cef_drag_data_t* self,
const cef_string_t* url);
///
// Set the title associated with the link being dragged.
///
void (CEF_CALLBACK *set_link_title)(struct _cef_drag_data_t* self,
const cef_string_t* title);
///
// Set the metadata associated with the link being dragged.
///
void (CEF_CALLBACK *set_link_metadata)(struct _cef_drag_data_t* self,
const cef_string_t* data);
///
// Set the plain text fragment that is being dragged.
///
void (CEF_CALLBACK *set_fragment_text)(struct _cef_drag_data_t* self,
const cef_string_t* text);
///
// Set the text/html fragment that is being dragged.
///
void (CEF_CALLBACK *set_fragment_html)(struct _cef_drag_data_t* self,
const cef_string_t* html);
///
// Set the base URL that the fragment came from.
///
void (CEF_CALLBACK *set_fragment_base_url)(struct _cef_drag_data_t* self,
const cef_string_t* base_url);
///
// Reset the file contents. You should do this before calling
// cef_browser_host_t::DragTargetDragEnter as the web view does not allow us
// to drag in this kind of data.
///
void (CEF_CALLBACK *reset_file_contents)(struct _cef_drag_data_t* self);
///
// Add a file that is being dragged into the webview.
///
void (CEF_CALLBACK *add_file)(struct _cef_drag_data_t* self,
const cef_string_t* path, const cef_string_t* display_name);
} cef_drag_data_t;
///
// Create a new cef_drag_data_t object.
///
CEF_EXPORT cef_drag_data_t* cef_drag_data_create();
#ifdef __cplusplus
}
#endif

View File

@ -40,6 +40,7 @@
#include "include/capi/cef_base_capi.h"
#include "include/capi/cef_browser_capi.h"
#include "include/capi/cef_drag_data_capi.h"
#ifdef __cplusplus
extern "C" {
@ -122,6 +123,31 @@ typedef struct _cef_render_handler_t {
void (CEF_CALLBACK *on_cursor_change)(struct _cef_render_handler_t* self,
struct _cef_browser_t* browser, cef_cursor_handle_t cursor);
///
// Called when the user starts dragging content in the web view. Contextual
// information about the dragged content is supplied by |drag_data|. OS APIs
// that run a system message loop may be used within the StartDragging call.
//
// Return false (0) to abort the drag operation. Don't call any of
// cef_browser_host_t::DragSource*Ended* functions after returning false (0).
//
// Return true (1) to handle the drag operation. Call
// cef_browser_host_t::DragSourceEndedAt and DragSourceSystemDragEnded either
// synchronously or asynchronously to inform the web view that the drag
// operation has ended.
///
int (CEF_CALLBACK *start_dragging)(struct _cef_render_handler_t* self,
struct _cef_browser_t* browser, struct _cef_drag_data_t* drag_data,
cef_drag_operations_mask_t allowed_ops, int x, int y);
///
// Called when the web view wants to update the mouse cursor during a drag &
// drop operation. |operation| describes the allowed operation (none, move,
// copy, link).
///
void (CEF_CALLBACK *update_drag_cursor)(struct _cef_render_handler_t* self,
struct _cef_browser_t* browser, cef_drag_operations_mask_t operation);
///
// Called when the scroll offset has changed.
///

View File

@ -39,6 +39,7 @@
#pragma once
#include "include/cef_base.h"
#include "include/cef_drag_data.h"
#include "include/cef_frame.h"
#include "include/cef_process_message.h"
#include "include/cef_request_context.h"
@ -218,6 +219,7 @@ class CefRunFileDialogCallback : public virtual CefBase {
/*--cef(source=library)--*/
class CefBrowserHost : public virtual CefBase {
public:
typedef cef_drag_operations_mask_t DragOperationsMask;
typedef cef_file_dialog_mode_t FileDialogMode;
typedef cef_mouse_button_type_t MouseButtonType;
typedef cef_paint_element_type_t PaintElementType;
@ -503,6 +505,72 @@ class CefBrowserHost : public virtual CefBase {
///
/*--cef()--*/
virtual void HandleKeyEventAfterTextInputClient(CefEventHandle keyEvent) =0;
///
// Call this method when the user drags the mouse into the web view (before
// calling DragTargetDragOver/DragTargetLeave/DragTargetDrop).
// |drag_data| should not contain file contents as this type of data is not
// allowed to be dragged into the web view. File contents can be removed using
// CefDragData::ResetFileContents (for example, if |drag_data| comes from
// CefRenderHandler::StartDragging).
// This method is only used when window rendering is disabled.
///
/*--cef()--*/
virtual void DragTargetDragEnter(CefRefPtr<CefDragData> drag_data,
const CefMouseEvent& event,
DragOperationsMask allowed_ops) =0;
///
// Call this method each time the mouse is moved across the web view during
// a drag operation (after calling DragTargetDragEnter and before calling
// DragTargetDragLeave/DragTargetDrop).
// This method is only used when window rendering is disabled.
///
/*--cef()--*/
virtual void DragTargetDragOver(const CefMouseEvent& event,
DragOperationsMask allowed_ops) =0;
///
// Call this method when the user drags the mouse out of the web view (after
// calling DragTargetDragEnter).
// This method is only used when window rendering is disabled.
///
/*--cef()--*/
virtual void DragTargetDragLeave() =0;
///
// Call this method when the user completes the drag operation by dropping
// the object onto the web view (after calling DragTargetDragEnter).
// The object being dropped is |drag_data|, given as an argument to
// the previous DragTargetDragEnter call.
// This method is only used when window rendering is disabled.
///
/*--cef()--*/
virtual void DragTargetDrop(const CefMouseEvent& event) =0;
///
// Call this method when the drag operation started by a
// CefRenderHandler::StartDragging call has ended either in a drop or
// by being cancelled. |x| and |y| are mouse coordinates relative to the
// upper-left corner of the view. If the web view is both the drag source
// and the drag target then all DragTarget* methods should be called before
// DragSource* mthods.
// This method is only used when window rendering is disabled.
///
/*--cef()--*/
virtual void DragSourceEndedAt(int x, int y, DragOperationsMask op) =0;
///
// Call this method when the drag operation started by a
// CefRenderHandler::StartDragging call has completed. This method may be
// called immediately without first calling DragSourceEndedAt to cancel a
// drag operation. If the web view is both the drag source and the drag
// target then all DragTarget* methods should be called before DragSource*
// mthods.
// This method is only used when window rendering is disabled.
///
/*--cef()--*/
virtual void DragSourceSystemDragEnded() =0;
};
#endif // CEF_INCLUDE_CEF_BROWSER_H_

View File

@ -39,6 +39,7 @@
#pragma once
#include "include/cef_base.h"
#include "include/cef_stream.h"
#include <vector>
///
@ -48,6 +49,24 @@
/*--cef(source=library)--*/
class CefDragData : public virtual CefBase {
public:
///
// Create a new CefDragData object.
///
/*--cef()--*/
static CefRefPtr<CefDragData> Create();
///
// Returns a copy of the current object.
///
/*--cef()--*/
virtual CefRefPtr<CefDragData> Clone() =0;
///
// Returns true if this object is read-only.
///
/*--cef()--*/
virtual bool IsReadOnly() =0;
///
// Returns true if the drag data is a link.
///
@ -109,12 +128,71 @@ class CefDragData : public virtual CefBase {
/*--cef()--*/
virtual CefString GetFileName() =0;
///
// Write the contents of the file being dragged out of the web view into
// |writer|. Returns the number of bytes sent to |writer|. If |writer| is
// NULL this method will return the size of the file contents in bytes.
// Call GetFileName() to get a suggested name for the file.
///
/*--cef(optional_param=writer)--*/
virtual size_t GetFileContents(CefRefPtr<CefStreamWriter> writer) =0;
///
// Retrieve the list of file names that are being dragged into the browser
// window.
///
/*--cef()--*/
virtual bool GetFileNames(std::vector<CefString>& names) =0;
///
// Set the link URL that is being dragged.
///
/*--cef(optional_param=url)--*/
virtual void SetLinkURL(const CefString& url) =0;
///
// Set the title associated with the link being dragged.
///
/*--cef(optional_param=title)--*/
virtual void SetLinkTitle(const CefString& title) =0;
///
// Set the metadata associated with the link being dragged.
///
/*--cef(optional_param=data)--*/
virtual void SetLinkMetadata(const CefString& data) =0;
///
// Set the plain text fragment that is being dragged.
///
/*--cef(optional_param=text)--*/
virtual void SetFragmentText(const CefString& text) =0;
///
// Set the text/html fragment that is being dragged.
///
/*--cef(optional_param=html)--*/
virtual void SetFragmentHtml(const CefString& html) =0;
///
// Set the base URL that the fragment came from.
///
/*--cef(optional_param=base_url)--*/
virtual void SetFragmentBaseURL(const CefString& base_url) =0;
///
// Reset the file contents. You should do this before calling
// CefBrowserHost::DragTargetDragEnter as the web view does not allow us to
// drag in this kind of data.
///
/*--cef()--*/
virtual void ResetFileContents() =0;
///
// Add a file that is being dragged into the webview.
///
/*--cef(optional_param=display_name)--*/
virtual void AddFile(const CefString& path, const CefString& display_name) =0;
};
#endif // CEF_INCLUDE_CEF_DRAG_DATA_H_

View File

@ -40,6 +40,7 @@
#include "include/cef_base.h"
#include "include/cef_browser.h"
#include "include/cef_drag_data.h"
#include <vector>
///
@ -49,6 +50,8 @@
/*--cef(source=client)--*/
class CefRenderHandler : public virtual CefBase {
public:
typedef cef_drag_operations_mask_t DragOperation;
typedef cef_drag_operations_mask_t DragOperationsMask;
typedef cef_paint_element_type_t PaintElementType;
typedef std::vector<CefRect> RectList;
@ -128,6 +131,35 @@ class CefRenderHandler : public virtual CefBase {
virtual void OnCursorChange(CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor) {}
///
// Called when the user starts dragging content in the web view. Contextual
// information about the dragged content is supplied by |drag_data|.
// OS APIs that run a system message loop may be used within the
// StartDragging call.
//
// Return false to abort the drag operation. Don't call any of
// CefBrowserHost::DragSource*Ended* methods after returning false.
//
// Return true to handle the drag operation. Call
// CefBrowserHost::DragSourceEndedAt and DragSourceSystemDragEnded either
// synchronously or asynchronously to inform the web view that the drag
// operation has ended.
///
/*--cef()--*/
virtual bool StartDragging(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
DragOperationsMask allowed_ops,
int x, int y) { return false; }
///
// Called when the web view wants to update the mouse cursor during a
// drag & drop operation. |operation| describes the allowed operation
// (none, move, copy, link).
///
/*--cef()--*/
virtual void UpdateDragCursor(CefRefPtr<CefBrowser> browser,
DragOperation operation) {}
///
// Called when the scroll offset has changed.
///

View File

@ -930,7 +930,7 @@ void CefBrowserHostImpl::WasHidden(bool hidden) {
if (!widget)
return;
if (hidden)
if (hidden)
widget->WasHidden();
else
widget->WasShown();
@ -1729,6 +1729,190 @@ void CefBrowserHostImpl::HandleKeyEventAfterTextInputClient(
}
#endif // !defined(OS_MACOSX)
void CefBrowserHostImpl::DragTargetDragEnter(CefRefPtr<CefDragData> drag_data,
const CefMouseEvent& event,
CefBrowserHost::DragOperationsMask allowed_ops) {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefBrowserHostImpl::DragTargetDragEnter, this, drag_data,
event, allowed_ops));
return;
}
if (!drag_data.get()) {
NOTREACHED();
return;
}
if (!IsWindowRenderingDisabled()) {
NOTREACHED() << "Window rendering is not disabled";
return;
}
content::RenderViewHost* rvh =
web_contents() ? web_contents()->GetRenderViewHost() : NULL;
if (!rvh)
return;
int screenX, screenY;
if (!client_->GetRenderHandler()->GetScreenPoint(
this, event.x, event.y, screenX, screenY)) {
screenX = event.x;
screenY = event.y;
}
CefDragDataImpl* data_impl = static_cast<CefDragDataImpl*>(drag_data.get());
CefDragDataImpl::AutoLock lock_scope(data_impl);
const content::DropData& drop_data = data_impl->drop_data();
gfx::Point client_pt(event.x, event.y);
gfx::Point screen_pt(screenX, screenY);
blink::WebDragOperationsMask ops =
static_cast<blink::WebDragOperationsMask>(allowed_ops);
int modifiers = CefBrowserHostImpl::TranslateModifiers(event.modifiers);
rvh->DragTargetDragEnter(drop_data, client_pt, screen_pt, ops, modifiers);
}
void CefBrowserHostImpl::DragTargetDragOver(const CefMouseEvent& event,
CefBrowserHost::DragOperationsMask allowed_ops) {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefBrowserHostImpl::DragTargetDragOver, this, event,
allowed_ops));
return;
}
if (!IsWindowRenderingDisabled()) {
NOTREACHED() << "Window rendering is not disabled";
return;
}
content::RenderViewHost* rvh =
web_contents() ? web_contents()->GetRenderViewHost() : NULL;
if (!rvh)
return;
int screenX, screenY;
if (!client_->GetRenderHandler()->GetScreenPoint(
this, event.x, event.y, screenX, screenY)) {
screenX = event.x;
screenY = event.y;
}
gfx::Point client_pt(event.x, event.y);
gfx::Point screen_pt(screenX, screenY);
blink::WebDragOperationsMask ops =
static_cast<blink::WebDragOperationsMask>(allowed_ops);
int modifiers = CefBrowserHostImpl::TranslateModifiers(event.modifiers);
rvh->DragTargetDragOver(client_pt, screen_pt, ops, modifiers);
}
void CefBrowserHostImpl::DragTargetDragLeave() {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefBrowserHostImpl::DragTargetDragLeave, this));
return;
}
if (!IsWindowRenderingDisabled()) {
NOTREACHED() << "Window rendering is not disabled";
return;
}
content::RenderViewHost* rvh =
web_contents() ? web_contents()->GetRenderViewHost() : NULL;
if (!rvh)
return;
rvh->DragTargetDragLeave();
}
void CefBrowserHostImpl::DragTargetDrop(const CefMouseEvent& event) {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefBrowserHostImpl::DragTargetDrop, this, event));
return;
}
if (!IsWindowRenderingDisabled()) {
NOTREACHED() << "Window rendering is not disabled";
return;
}
content::RenderViewHost* rvh =
web_contents() ? web_contents()->GetRenderViewHost() : NULL;
if (!rvh)
return;
int screenX, screenY;
if (!client_->GetRenderHandler()->GetScreenPoint(
this, event.x, event.y, screenX, screenY)) {
screenX = event.x;
screenY = event.y;
}
gfx::Point client_pt(event.x, event.y);
gfx::Point screen_pt(screenX, screenY);
int modifiers = CefBrowserHostImpl::TranslateModifiers(event.modifiers);
rvh->DragTargetDrop(client_pt, screen_pt, modifiers);
}
void CefBrowserHostImpl::DragSourceSystemDragEnded() {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefBrowserHostImpl::DragSourceSystemDragEnded, this));
return;
}
if (!IsWindowRenderingDisabled()) {
NOTREACHED() << "Window rendering is not disabled";
return;
}
content::RenderViewHost* rvh =
web_contents() ? web_contents()->GetRenderViewHost() : NULL;
if (!rvh)
return;
rvh->DragSourceSystemDragEnded();
}
void CefBrowserHostImpl::DragSourceEndedAt(
int x, int y, CefBrowserHost::DragOperationsMask op) {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefBrowserHostImpl::DragSourceEndedAt, this, x, y, op));
return;
}
if (!IsWindowRenderingDisabled()) {
NOTREACHED() << "Window rendering is not disabled";
return;
}
content::RenderViewHost* rvh =
web_contents() ? web_contents()->GetRenderViewHost() : NULL;
if (!rvh)
return;
int screenX, screenY;
if (!client_->GetRenderHandler()->GetScreenPoint(
this, x, y, screenX, screenY)) {
screenX = x;
screenY = y;
}
blink::WebDragOperation drag_op = static_cast<blink::WebDragOperation>(op);
rvh->DragSourceEndedAt(x, y, screenX, screenY, drag_op);
}
// content::WebContentsDelegate methods.
// -----------------------------------------------------------------------------
@ -1921,9 +2105,12 @@ bool CefBrowserHostImpl::CanDragEnter(
blink::WebDragOperationsMask mask) {
CefRefPtr<CefDragHandler> handler = client_->GetDragHandler();
if (handler.get()) {
CefRefPtr<CefDragData> drag_data(new CefDragDataImpl(data));
if (handler->OnDragEnter(this, drag_data,
static_cast<CefDragHandler::DragOperationsMask>(mask))) {
CefRefPtr<CefDragDataImpl> drag_data(new CefDragDataImpl(data));
drag_data->SetReadOnly(true);
if (handler->OnDragEnter(
this,
drag_data.get(),
static_cast<CefDragHandler::DragOperationsMask>(mask))) {
return false;
}
}
@ -2046,7 +2233,7 @@ void CefBrowserHostImpl::RequestMediaAccessPermission(
// Based on chrome/browser/media/media_stream_devices_controller.cc
bool microphone_requested =
(request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE);
bool webcam_requested =
bool webcam_requested =
(request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE);
if (microphone_requested || webcam_requested) {
switch (request.request_type) {
@ -2089,8 +2276,9 @@ void CefBrowserHostImpl::RenderFrameCreated(
void CefBrowserHostImpl::RenderFrameDeleted(
content::RenderFrameHost* render_frame_host) {
browser_info_->remove_render_frame_id(render_frame_host->GetProcess()->GetID(),
render_frame_host->GetRoutingID());
browser_info_->remove_render_frame_id(
render_frame_host->GetProcess()->GetID(),
render_frame_host->GetRoutingID());
}
void CefBrowserHostImpl::RenderViewCreated(
@ -2515,7 +2703,7 @@ void CefBrowserHostImpl::DetachAllFrames() {
void CefBrowserHostImpl::SetFocusedFrame(int64 frame_id) {
CefRefPtr<CefFrameHostImpl> unfocused_frame;
CefRefPtr<CefFrameHostImpl> focused_frame;
{
base::AutoLock lock_scope(state_lock_);

View File

@ -171,6 +171,15 @@ class CefBrowserHostImpl : public CefBrowserHost,
OVERRIDE;
virtual void HandleKeyEventAfterTextInputClient(CefEventHandle keyEvent)
OVERRIDE;
virtual void DragTargetDragEnter(CefRefPtr<CefDragData> drag_data,
const CefMouseEvent& event,
DragOperationsMask allowed_ops);
virtual void DragTargetDragOver(const CefMouseEvent& event,
DragOperationsMask allowed_ops);
virtual void DragTargetDragLeave();
virtual void DragTargetDrop(const CefMouseEvent& event);
virtual void DragSourceSystemDragEnded();
virtual void DragSourceEndedAt(int x, int y, DragOperationsMask op);
// CefBrowser methods.
virtual CefRefPtr<CefBrowserHost> GetHost() OVERRIDE;

View File

@ -3,11 +3,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "libcef/browser/browser_host_impl.h"
#include "libcef/browser/render_widget_host_view_osr.h"
#include "libcef/browser/web_contents_view_osr.h"
#include "libcef/common/drag_data_impl.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/drop_data.h"
#include "ui/base/dragdrop/drag_utils.h"
CefWebContentsViewOSR::CefWebContentsViewOSR(
content::WebContents* web_contents,
@ -134,8 +138,46 @@ void CefWebContentsViewOSR::StartDragging(
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
const content::DragEventSourceInfo& event_info) {
// Dragging is not supported when window rendering is disabled.
web_contents_->SystemDragEnded();
CefRefPtr<CefBrowserHostImpl> browser;
CefRefPtr<CefRenderHandler> handler;
bool handled = false;
CefRenderWidgetHostViewOSR* view =
static_cast<CefRenderWidgetHostViewOSR*>(view_);
if (view)
browser = view->get_browser_impl();
if (browser.get())
handler = browser->GetClient()->GetRenderHandler();
DCHECK(handler.get());
if (handler.get()) {
CefRefPtr<CefDragDataImpl> drag_data(new CefDragDataImpl(drop_data));
drag_data->SetReadOnly(true);
base::MessageLoop::ScopedNestableTaskAllower allow(
base::MessageLoop::current());
handled = handler->StartDragging(browser->GetBrowser(),
drag_data.get(),
static_cast<CefRenderHandler::DragOperationsMask>(allowed_ops),
event_info.event_location.x(),
event_info.event_location.y());
}
if (!handled)
web_contents_->SystemDragEnded();
}
void CefWebContentsViewOSR::UpdateDragCursor(
blink::WebDragOperation operation) {
CefRefPtr<CefBrowserHostImpl> browser;
CefRefPtr<CefRenderHandler> handler;
CefRenderWidgetHostViewOSR* view =
static_cast<CefRenderWidgetHostViewOSR*>(view_);
if (view)
browser = view->get_browser_impl();
if (browser.get())
handler = browser->GetClient()->GetRenderHandler();
DCHECK(handler.get());
if (handler.get()) {
handler->UpdateDragCursor(browser->GetBrowser(),
static_cast<CefRenderHandler::DragOperation>(operation));
}
}
void CefWebContentsViewOSR::ShowPopupMenu(

View File

@ -67,6 +67,7 @@ class CefWebContentsViewOSR : public content::WebContentsViewPort,
const gfx::ImageSkia& image,
const gfx::Vector2d& image_offset,
const content::DragEventSourceInfo& event_info) OVERRIDE;
virtual void UpdateDragCursor(blink::WebDragOperation operation) OVERRIDE;
virtual void ShowPopupMenu(
const gfx::Rect& bounds,
int item_height,

View File

@ -2,55 +2,126 @@
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include <string>
#include "libcef/browser/stream_impl.h"
#include "libcef/common/drag_data_impl.h"
#include "base/files/file_path.h"
#include "net/base/net_util.h"
#define CHECK_READONLY_RETURN_VOID() \
if (read_only_) { \
NOTREACHED() << "object is read only"; \
return; \
}
CefDragDataImpl::CefDragDataImpl(const content::DropData& data)
: data_(data) {
: data_(data),
read_only_(false) {
}
CefDragDataImpl::CefDragDataImpl()
: read_only_(false) {
}
CefRefPtr<CefDragData> CefDragData::Create() {
return new CefDragDataImpl();
}
CefRefPtr<CefDragData> CefDragDataImpl::Clone() {
CefDragDataImpl* drag_data = NULL;
{
AutoLock lock_scope(this);
drag_data = new CefDragDataImpl(data_);
}
return drag_data;
}
bool CefDragDataImpl::IsReadOnly() {
AutoLock lock_scope(this);
return read_only_;
}
bool CefDragDataImpl::IsLink() {
AutoLock lock_scope(this);
return (data_.url.is_valid() && data_.file_description_filename.empty());
}
bool CefDragDataImpl::IsFragment() {
AutoLock lock_scope(this);
return (!data_.url.is_valid() && data_.file_description_filename.empty() &&
data_.filenames.empty());
}
bool CefDragDataImpl::IsFile() {
AutoLock lock_scope(this);
return (!data_.file_description_filename.empty() || !data_.filenames.empty());
}
CefString CefDragDataImpl::GetLinkURL() {
AutoLock lock_scope(this);
return data_.url.spec();
}
CefString CefDragDataImpl::GetLinkTitle() {
AutoLock lock_scope(this);
return data_.url_title;
}
CefString CefDragDataImpl::GetLinkMetadata() {
AutoLock lock_scope(this);
return data_.download_metadata;
}
CefString CefDragDataImpl::GetFragmentText() {
AutoLock lock_scope(this);
return data_.text.is_null() ? CefString() : CefString(data_.text.string());
}
CefString CefDragDataImpl::GetFragmentHtml() {
AutoLock lock_scope(this);
return data_.html.is_null() ? CefString() : CefString(data_.html.string());
}
CefString CefDragDataImpl::GetFragmentBaseURL() {
AutoLock lock_scope(this);
return data_.html_base_url.spec();
}
CefString CefDragDataImpl::GetFileName() {
return data_.file_description_filename;
AutoLock lock_scope(this);
if (data_.file_description_filename.empty())
return CefString();
base::FilePath file_name(CefString(data_.file_description_filename));
// Images without ALT text will only have a file extension so we need to
// synthesize one from the provided extension and URL.
if (file_name.BaseName().RemoveExtension().empty()) {
CefString extension = file_name.Extension();
// Retrieve the name from the URL.
CefString suggested_file_name =
net::GetSuggestedFilename(data_.url, "", "", "", "", "");
file_name = base::FilePath(suggested_file_name).ReplaceExtension(extension);
}
return file_name.value();
}
size_t CefDragDataImpl::GetFileContents(CefRefPtr<CefStreamWriter> writer) {
AutoLock lock_scope(this);
if (data_.file_contents.empty())
return 0;
char* data = const_cast<char*>(data_.file_contents.c_str());
size_t size = data_.file_contents.size();
if (!writer.get())
return size;
return writer->Write(data, 1, size);
}
bool CefDragDataImpl::GetFileNames(std::vector<CefString>& names) {
AutoLock lock_scope(this);
if (data_.filenames.empty())
return false;
@ -61,3 +132,62 @@ bool CefDragDataImpl::GetFileNames(std::vector<CefString>& names) {
return true;
}
void CefDragDataImpl::SetLinkURL(const CefString& url) {
AutoLock lock_scope(this);
CHECK_READONLY_RETURN_VOID();
data_.url = GURL(url.ToString());
}
void CefDragDataImpl::SetLinkTitle(const CefString& title) {
AutoLock lock_scope(this);
CHECK_READONLY_RETURN_VOID();
data_.url_title = title.ToString16();
}
void CefDragDataImpl::SetLinkMetadata(const CefString& data) {
AutoLock lock_scope(this);
CHECK_READONLY_RETURN_VOID();
data_.download_metadata = data.ToString16();
}
void CefDragDataImpl::SetFragmentText(const CefString& text) {
AutoLock lock_scope(this);
CHECK_READONLY_RETURN_VOID();
data_.text = base::NullableString16(text.ToString16(), false);
}
void CefDragDataImpl::SetFragmentHtml(const CefString& fragment) {
AutoLock lock_scope(this);
CHECK_READONLY_RETURN_VOID();
data_.html = base::NullableString16(fragment.ToString16(), false);
}
void CefDragDataImpl::SetFragmentBaseURL(const CefString& fragment) {
AutoLock lock_scope(this);
CHECK_READONLY_RETURN_VOID();
data_.html_base_url = GURL(fragment.ToString());
}
void CefDragDataImpl::ResetFileContents() {
AutoLock lock_scope(this);
CHECK_READONLY_RETURN_VOID();
data_.file_contents.erase();
data_.file_description_filename.erase();
}
void CefDragDataImpl::AddFile(const CefString& path,
const CefString& display_name) {
AutoLock lock_scope(this);
CHECK_READONLY_RETURN_VOID();
data_.filenames.push_back(ui::FileInfo(base::FilePath(path),
base::FilePath(display_name)));
}
void CefDragDataImpl::SetReadOnly(bool read_only) {
AutoLock lock_scope(this);
if (read_only_ == read_only)
return;
read_only_ = read_only;
}

View File

@ -14,7 +14,10 @@
// Implementation of CefDragData.
class CefDragDataImpl : public CefDragData {
public:
CefDragDataImpl();
explicit CefDragDataImpl(const content::DropData& data);
virtual CefRefPtr<CefDragData> Clone();
virtual bool IsReadOnly();
virtual bool IsLink();
virtual bool IsFragment();
@ -26,12 +29,33 @@ class CefDragDataImpl : public CefDragData {
virtual CefString GetFragmentHtml();
virtual CefString GetFragmentBaseURL();
virtual CefString GetFileName();
virtual size_t GetFileContents(CefRefPtr<CefStreamWriter> writer);
virtual bool GetFileNames(std::vector<CefString>& names);
virtual void SetLinkURL(const CefString& url);
virtual void SetLinkTitle(const CefString& title);
virtual void SetLinkMetadata(const CefString& data);
virtual void SetFragmentText(const CefString& text);
virtual void SetFragmentHtml(const CefString& fragment);
virtual void SetFragmentBaseURL(const CefString& fragment);
virtual void ResetFileContents();
virtual void AddFile(const CefString& path, const CefString& display_name);
// This method is not safe. Use Lock/Unlock to get mutually exclusive access.
const content::DropData& drop_data() {
return data_;
}
void SetReadOnly(bool read_only);
protected:
content::DropData data_;
// True if this object is read-only.
bool read_only_;
IMPLEMENT_REFCOUNTING(CefDragDataImpl);
IMPLEMENT_LOCKING(CefDragDataImpl);
};
#endif // CEF_LIBCEF_COMMON_DRAG_DATA_IMPL_H_

View File

@ -12,6 +12,7 @@
#include "libcef_dll/cpptoc/browser_cpptoc.h"
#include "libcef_dll/cpptoc/browser_host_cpptoc.h"
#include "libcef_dll/cpptoc/drag_data_cpptoc.h"
#include "libcef_dll/cpptoc/request_context_cpptoc.h"
#include "libcef_dll/ctocpp/client_ctocpp.h"
#include "libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h"
@ -633,6 +634,122 @@ void CEF_CALLBACK browser_host_handle_key_event_after_text_input_client(
keyEvent);
}
void CEF_CALLBACK browser_host_drag_target_drag_enter(
struct _cef_browser_host_t* self, struct _cef_drag_data_t* drag_data,
const struct _cef_mouse_event_t* event,
cef_drag_operations_mask_t allowed_ops) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: drag_data; type: refptr_same
DCHECK(drag_data);
if (!drag_data)
return;
// Verify param: event; type: struct_byref_const
DCHECK(event);
if (!event)
return;
// Translate param: event; type: struct_byref_const
CefMouseEvent eventObj;
if (event)
eventObj.Set(*event, false);
// Execute
CefBrowserHostCppToC::Get(self)->DragTargetDragEnter(
CefDragDataCppToC::Unwrap(drag_data),
eventObj,
allowed_ops);
}
void CEF_CALLBACK browser_host_drag_target_drag_over(
struct _cef_browser_host_t* self, const struct _cef_mouse_event_t* event,
cef_drag_operations_mask_t allowed_ops) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: event; type: struct_byref_const
DCHECK(event);
if (!event)
return;
// Translate param: event; type: struct_byref_const
CefMouseEvent eventObj;
if (event)
eventObj.Set(*event, false);
// Execute
CefBrowserHostCppToC::Get(self)->DragTargetDragOver(
eventObj,
allowed_ops);
}
void CEF_CALLBACK browser_host_drag_target_drag_leave(
struct _cef_browser_host_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Execute
CefBrowserHostCppToC::Get(self)->DragTargetDragLeave();
}
void CEF_CALLBACK browser_host_drag_target_drop(
struct _cef_browser_host_t* self, const struct _cef_mouse_event_t* event) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: event; type: struct_byref_const
DCHECK(event);
if (!event)
return;
// Translate param: event; type: struct_byref_const
CefMouseEvent eventObj;
if (event)
eventObj.Set(*event, false);
// Execute
CefBrowserHostCppToC::Get(self)->DragTargetDrop(
eventObj);
}
void CEF_CALLBACK browser_host_drag_source_ended_at(
struct _cef_browser_host_t* self, int x, int y,
cef_drag_operations_mask_t op) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Execute
CefBrowserHostCppToC::Get(self)->DragSourceEndedAt(
x,
y,
op);
}
void CEF_CALLBACK browser_host_drag_source_system_drag_ended(
struct _cef_browser_host_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Execute
CefBrowserHostCppToC::Get(self)->DragSourceSystemDragEnded();
}
// CONSTRUCTOR - Do not edit by hand.
@ -679,6 +796,13 @@ CefBrowserHostCppToC::CefBrowserHostCppToC(CefBrowserHost* cls)
browser_host_handle_key_event_before_text_input_client;
struct_.struct_.handle_key_event_after_text_input_client =
browser_host_handle_key_event_after_text_input_client;
struct_.struct_.drag_target_drag_enter = browser_host_drag_target_drag_enter;
struct_.struct_.drag_target_drag_over = browser_host_drag_target_drag_over;
struct_.struct_.drag_target_drag_leave = browser_host_drag_target_drag_leave;
struct_.struct_.drag_target_drop = browser_host_drag_target_drop;
struct_.struct_.drag_source_ended_at = browser_host_drag_source_ended_at;
struct_.struct_.drag_source_system_drag_ended =
browser_host_drag_source_system_drag_ended;
}
#ifndef NDEBUG

View File

@ -11,11 +11,54 @@
//
#include "libcef_dll/cpptoc/drag_data_cpptoc.h"
#include "libcef_dll/cpptoc/stream_writer_cpptoc.h"
#include "libcef_dll/transfer_util.h"
// GLOBAL FUNCTIONS - Body may be edited by hand.
CEF_EXPORT cef_drag_data_t* cef_drag_data_create() {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
CefRefPtr<CefDragData> _retval = CefDragData::Create();
// Return type: refptr_same
return CefDragDataCppToC::Wrap(_retval);
}
// MEMBER FUNCTIONS - Body may be edited by hand.
struct _cef_drag_data_t* CEF_CALLBACK drag_data_clone(
struct _cef_drag_data_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return NULL;
// Execute
CefRefPtr<CefDragData> _retval = CefDragDataCppToC::Get(self)->Clone();
// Return type: refptr_same
return CefDragDataCppToC::Wrap(_retval);
}
int CEF_CALLBACK drag_data_is_read_only(struct _cef_drag_data_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Execute
bool _retval = CefDragDataCppToC::Get(self)->IsReadOnly();
// Return type: bool
return _retval;
}
int CEF_CALLBACK drag_data_is_link(struct _cef_drag_data_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
@ -163,6 +206,23 @@ cef_string_userfree_t CEF_CALLBACK drag_data_get_file_name(
return _retval.DetachToUserFree();
}
size_t CEF_CALLBACK drag_data_get_file_contents(struct _cef_drag_data_t* self,
struct _cef_stream_writer_t* writer) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Unverified params: writer
// Execute
size_t _retval = CefDragDataCppToC::Get(self)->GetFileContents(
CefStreamWriterCppToC::Unwrap(writer));
// Return type: simple
return _retval;
}
int CEF_CALLBACK drag_data_get_file_names(struct _cef_drag_data_t* self,
cef_string_list_t names) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
@ -191,11 +251,127 @@ int CEF_CALLBACK drag_data_get_file_names(struct _cef_drag_data_t* self,
return _retval;
}
void CEF_CALLBACK drag_data_set_link_url(struct _cef_drag_data_t* self,
const cef_string_t* url) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Unverified params: url
// Execute
CefDragDataCppToC::Get(self)->SetLinkURL(
CefString(url));
}
void CEF_CALLBACK drag_data_set_link_title(struct _cef_drag_data_t* self,
const cef_string_t* title) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Unverified params: title
// Execute
CefDragDataCppToC::Get(self)->SetLinkTitle(
CefString(title));
}
void CEF_CALLBACK drag_data_set_link_metadata(struct _cef_drag_data_t* self,
const cef_string_t* data) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Unverified params: data
// Execute
CefDragDataCppToC::Get(self)->SetLinkMetadata(
CefString(data));
}
void CEF_CALLBACK drag_data_set_fragment_text(struct _cef_drag_data_t* self,
const cef_string_t* text) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Unverified params: text
// Execute
CefDragDataCppToC::Get(self)->SetFragmentText(
CefString(text));
}
void CEF_CALLBACK drag_data_set_fragment_html(struct _cef_drag_data_t* self,
const cef_string_t* html) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Unverified params: html
// Execute
CefDragDataCppToC::Get(self)->SetFragmentHtml(
CefString(html));
}
void CEF_CALLBACK drag_data_set_fragment_base_url(struct _cef_drag_data_t* self,
const cef_string_t* base_url) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Unverified params: base_url
// Execute
CefDragDataCppToC::Get(self)->SetFragmentBaseURL(
CefString(base_url));
}
void CEF_CALLBACK drag_data_reset_file_contents(struct _cef_drag_data_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Execute
CefDragDataCppToC::Get(self)->ResetFileContents();
}
void CEF_CALLBACK drag_data_add_file(struct _cef_drag_data_t* self,
const cef_string_t* path, const cef_string_t* display_name) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: path; type: string_byref_const
DCHECK(path);
if (!path)
return;
// Unverified params: display_name
// Execute
CefDragDataCppToC::Get(self)->AddFile(
CefString(path),
CefString(display_name));
}
// CONSTRUCTOR - Do not edit by hand.
CefDragDataCppToC::CefDragDataCppToC(CefDragData* cls)
: CefCppToC<CefDragDataCppToC, CefDragData, cef_drag_data_t>(cls) {
struct_.struct_.clone = drag_data_clone;
struct_.struct_.is_read_only = drag_data_is_read_only;
struct_.struct_.is_link = drag_data_is_link;
struct_.struct_.is_fragment = drag_data_is_fragment;
struct_.struct_.is_file = drag_data_is_file;
@ -206,7 +382,16 @@ CefDragDataCppToC::CefDragDataCppToC(CefDragData* cls)
struct_.struct_.get_fragment_html = drag_data_get_fragment_html;
struct_.struct_.get_fragment_base_url = drag_data_get_fragment_base_url;
struct_.struct_.get_file_name = drag_data_get_file_name;
struct_.struct_.get_file_contents = drag_data_get_file_contents;
struct_.struct_.get_file_names = drag_data_get_file_names;
struct_.struct_.set_link_url = drag_data_set_link_url;
struct_.struct_.set_link_title = drag_data_set_link_title;
struct_.struct_.set_link_metadata = drag_data_set_link_metadata;
struct_.struct_.set_fragment_text = drag_data_set_fragment_text;
struct_.struct_.set_fragment_html = drag_data_set_fragment_html;
struct_.struct_.set_fragment_base_url = drag_data_set_fragment_base_url;
struct_.struct_.reset_file_contents = drag_data_reset_file_contents;
struct_.struct_.add_file = drag_data_add_file;
}
#ifndef NDEBUG

View File

@ -12,6 +12,7 @@
#include "libcef_dll/cpptoc/render_handler_cpptoc.h"
#include "libcef_dll/ctocpp/browser_ctocpp.h"
#include "libcef_dll/ctocpp/drag_data_ctocpp.h"
// MEMBER FUNCTIONS - Body may be edited by hand.
@ -265,6 +266,55 @@ void CEF_CALLBACK render_handler_on_cursor_change(
cursor);
}
int CEF_CALLBACK render_handler_start_dragging(
struct _cef_render_handler_t* self, cef_browser_t* browser,
cef_drag_data_t* drag_data, cef_drag_operations_mask_t allowed_ops, int x,
int y) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser)
return 0;
// Verify param: drag_data; type: refptr_diff
DCHECK(drag_data);
if (!drag_data)
return 0;
// Execute
bool _retval = CefRenderHandlerCppToC::Get(self)->StartDragging(
CefBrowserCToCpp::Wrap(browser),
CefDragDataCToCpp::Wrap(drag_data),
allowed_ops,
x,
y);
// Return type: bool
return _retval;
}
void CEF_CALLBACK render_handler_update_drag_cursor(
struct _cef_render_handler_t* self, cef_browser_t* browser,
cef_drag_operations_mask_t operation) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser)
return;
// Execute
CefRenderHandlerCppToC::Get(self)->UpdateDragCursor(
CefBrowserCToCpp::Wrap(browser),
operation);
}
void CEF_CALLBACK render_handler_on_scroll_offset_changed(
struct _cef_render_handler_t* self, cef_browser_t* browser) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
@ -296,6 +346,8 @@ CefRenderHandlerCppToC::CefRenderHandlerCppToC(CefRenderHandler* cls)
struct_.struct_.on_popup_size = render_handler_on_popup_size;
struct_.struct_.on_paint = render_handler_on_paint;
struct_.struct_.on_cursor_change = render_handler_on_cursor_change;
struct_.struct_.start_dragging = render_handler_start_dragging;
struct_.struct_.update_drag_cursor = render_handler_update_drag_cursor;
struct_.struct_.on_scroll_offset_changed =
render_handler_on_scroll_offset_changed;
}

View File

@ -14,6 +14,7 @@
#include "libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h"
#include "libcef_dll/ctocpp/browser_ctocpp.h"
#include "libcef_dll/ctocpp/browser_host_ctocpp.h"
#include "libcef_dll/ctocpp/drag_data_ctocpp.h"
#include "libcef_dll/ctocpp/request_context_ctocpp.h"
#include "libcef_dll/transfer_util.h"
@ -487,6 +488,83 @@ void CefBrowserHostCToCpp::HandleKeyEventAfterTextInputClient(
keyEvent);
}
void CefBrowserHostCToCpp::DragTargetDragEnter(CefRefPtr<CefDragData> drag_data,
const CefMouseEvent& event, DragOperationsMask allowed_ops) {
if (CEF_MEMBER_MISSING(struct_, drag_target_drag_enter))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: drag_data; type: refptr_same
DCHECK(drag_data.get());
if (!drag_data.get())
return;
// Execute
struct_->drag_target_drag_enter(struct_,
CefDragDataCToCpp::Unwrap(drag_data),
&event,
allowed_ops);
}
void CefBrowserHostCToCpp::DragTargetDragOver(const CefMouseEvent& event,
DragOperationsMask allowed_ops) {
if (CEF_MEMBER_MISSING(struct_, drag_target_drag_over))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
struct_->drag_target_drag_over(struct_,
&event,
allowed_ops);
}
void CefBrowserHostCToCpp::DragTargetDragLeave() {
if (CEF_MEMBER_MISSING(struct_, drag_target_drag_leave))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
struct_->drag_target_drag_leave(struct_);
}
void CefBrowserHostCToCpp::DragTargetDrop(const CefMouseEvent& event) {
if (CEF_MEMBER_MISSING(struct_, drag_target_drop))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
struct_->drag_target_drop(struct_,
&event);
}
void CefBrowserHostCToCpp::DragSourceEndedAt(int x, int y,
DragOperationsMask op) {
if (CEF_MEMBER_MISSING(struct_, drag_source_ended_at))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
struct_->drag_source_ended_at(struct_,
x,
y,
op);
}
void CefBrowserHostCToCpp::DragSourceSystemDragEnded() {
if (CEF_MEMBER_MISSING(struct_, drag_source_system_drag_ended))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
struct_->drag_source_system_drag_ended(struct_);
}
#ifndef NDEBUG
template<> long CefCToCpp<CefBrowserHostCToCpp, CefBrowserHost,

View File

@ -81,6 +81,14 @@ class CefBrowserHostCToCpp
CefEventHandle keyEvent) OVERRIDE;
virtual void HandleKeyEventAfterTextInputClient(
CefEventHandle keyEvent) OVERRIDE;
virtual void DragTargetDragEnter(CefRefPtr<CefDragData> drag_data,
const CefMouseEvent& event, DragOperationsMask allowed_ops) OVERRIDE;
virtual void DragTargetDragOver(const CefMouseEvent& event,
DragOperationsMask allowed_ops) OVERRIDE;
virtual void DragTargetDragLeave() OVERRIDE;
virtual void DragTargetDrop(const CefMouseEvent& event) OVERRIDE;
virtual void DragSourceEndedAt(int x, int y, DragOperationsMask op) OVERRIDE;
virtual void DragSourceSystemDragEnded() OVERRIDE;
};
#endif // USING_CEF_SHARED

View File

@ -11,11 +11,51 @@
//
#include "libcef_dll/ctocpp/drag_data_ctocpp.h"
#include "libcef_dll/ctocpp/stream_writer_ctocpp.h"
#include "libcef_dll/transfer_util.h"
// STATIC METHODS - Body may be edited by hand.
CefRefPtr<CefDragData> CefDragData::Create() {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
cef_drag_data_t* _retval = cef_drag_data_create();
// Return type: refptr_same
return CefDragDataCToCpp::Wrap(_retval);
}
// VIRTUAL METHODS - Body may be edited by hand.
CefRefPtr<CefDragData> CefDragDataCToCpp::Clone() {
if (CEF_MEMBER_MISSING(struct_, clone))
return NULL;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
cef_drag_data_t* _retval = struct_->clone(struct_);
// Return type: refptr_same
return CefDragDataCToCpp::Wrap(_retval);
}
bool CefDragDataCToCpp::IsReadOnly() {
if (CEF_MEMBER_MISSING(struct_, is_read_only))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
int _retval = struct_->is_read_only(struct_);
// Return type: bool
return _retval?true:false;
}
bool CefDragDataCToCpp::IsLink() {
if (CEF_MEMBER_MISSING(struct_, is_link))
return false;
@ -160,6 +200,22 @@ CefString CefDragDataCToCpp::GetFileName() {
return _retvalStr;
}
size_t CefDragDataCToCpp::GetFileContents(CefRefPtr<CefStreamWriter> writer) {
if (CEF_MEMBER_MISSING(struct_, get_file_contents))
return 0;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Unverified params: writer
// Execute
size_t _retval = struct_->get_file_contents(struct_,
CefStreamWriterCToCpp::Unwrap(writer));
// Return type: simple
return _retval;
}
bool CefDragDataCToCpp::GetFileNames(std::vector<CefString>& names) {
if (CEF_MEMBER_MISSING(struct_, get_file_names))
return false;
@ -187,6 +243,113 @@ bool CefDragDataCToCpp::GetFileNames(std::vector<CefString>& names) {
return _retval?true:false;
}
void CefDragDataCToCpp::SetLinkURL(const CefString& url) {
if (CEF_MEMBER_MISSING(struct_, set_link_url))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Unverified params: url
// Execute
struct_->set_link_url(struct_,
url.GetStruct());
}
void CefDragDataCToCpp::SetLinkTitle(const CefString& title) {
if (CEF_MEMBER_MISSING(struct_, set_link_title))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Unverified params: title
// Execute
struct_->set_link_title(struct_,
title.GetStruct());
}
void CefDragDataCToCpp::SetLinkMetadata(const CefString& data) {
if (CEF_MEMBER_MISSING(struct_, set_link_metadata))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Unverified params: data
// Execute
struct_->set_link_metadata(struct_,
data.GetStruct());
}
void CefDragDataCToCpp::SetFragmentText(const CefString& text) {
if (CEF_MEMBER_MISSING(struct_, set_fragment_text))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Unverified params: text
// Execute
struct_->set_fragment_text(struct_,
text.GetStruct());
}
void CefDragDataCToCpp::SetFragmentHtml(const CefString& html) {
if (CEF_MEMBER_MISSING(struct_, set_fragment_html))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Unverified params: html
// Execute
struct_->set_fragment_html(struct_,
html.GetStruct());
}
void CefDragDataCToCpp::SetFragmentBaseURL(const CefString& base_url) {
if (CEF_MEMBER_MISSING(struct_, set_fragment_base_url))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Unverified params: base_url
// Execute
struct_->set_fragment_base_url(struct_,
base_url.GetStruct());
}
void CefDragDataCToCpp::ResetFileContents() {
if (CEF_MEMBER_MISSING(struct_, reset_file_contents))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
struct_->reset_file_contents(struct_);
}
void CefDragDataCToCpp::AddFile(const CefString& path,
const CefString& display_name) {
if (CEF_MEMBER_MISSING(struct_, add_file))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: path; type: string_byref_const
DCHECK(!path.empty());
if (path.empty())
return;
// Unverified params: display_name
// Execute
struct_->add_file(struct_,
path.GetStruct(),
display_name.GetStruct());
}
#ifndef NDEBUG
template<> long CefCToCpp<CefDragDataCToCpp, CefDragData,

View File

@ -33,6 +33,8 @@ class CefDragDataCToCpp
virtual ~CefDragDataCToCpp() {}
// CefDragData methods
virtual CefRefPtr<CefDragData> Clone() OVERRIDE;
virtual bool IsReadOnly() OVERRIDE;
virtual bool IsLink() OVERRIDE;
virtual bool IsFragment() OVERRIDE;
virtual bool IsFile() OVERRIDE;
@ -43,7 +45,17 @@ class CefDragDataCToCpp
virtual CefString GetFragmentHtml() OVERRIDE;
virtual CefString GetFragmentBaseURL() OVERRIDE;
virtual CefString GetFileName() OVERRIDE;
virtual size_t GetFileContents(CefRefPtr<CefStreamWriter> writer) OVERRIDE;
virtual bool GetFileNames(std::vector<CefString>& names) OVERRIDE;
virtual void SetLinkURL(const CefString& url) OVERRIDE;
virtual void SetLinkTitle(const CefString& title) OVERRIDE;
virtual void SetLinkMetadata(const CefString& data) OVERRIDE;
virtual void SetFragmentText(const CefString& text) OVERRIDE;
virtual void SetFragmentHtml(const CefString& html) OVERRIDE;
virtual void SetFragmentBaseURL(const CefString& base_url) OVERRIDE;
virtual void ResetFileContents() OVERRIDE;
virtual void AddFile(const CefString& path,
const CefString& display_name) OVERRIDE;
};
#endif // USING_CEF_SHARED

View File

@ -11,6 +11,7 @@
//
#include "libcef_dll/cpptoc/browser_cpptoc.h"
#include "libcef_dll/cpptoc/drag_data_cpptoc.h"
#include "libcef_dll/ctocpp/render_handler_ctocpp.h"
@ -202,6 +203,53 @@ void CefRenderHandlerCToCpp::OnCursorChange(CefRefPtr<CefBrowser> browser,
cursor);
}
bool CefRenderHandlerCToCpp::StartDragging(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data, DragOperationsMask allowed_ops, int x,
int y) {
if (CEF_MEMBER_MISSING(struct_, start_dragging))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get())
return false;
// Verify param: drag_data; type: refptr_diff
DCHECK(drag_data.get());
if (!drag_data.get())
return false;
// Execute
int _retval = struct_->start_dragging(struct_,
CefBrowserCppToC::Wrap(browser),
CefDragDataCppToC::Wrap(drag_data),
allowed_ops,
x,
y);
// Return type: bool
return _retval?true:false;
}
void CefRenderHandlerCToCpp::UpdateDragCursor(CefRefPtr<CefBrowser> browser,
DragOperation operation) {
if (CEF_MEMBER_MISSING(struct_, update_drag_cursor))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get())
return;
// Execute
struct_->update_drag_cursor(struct_,
CefBrowserCppToC::Wrap(browser),
operation);
}
void CefRenderHandlerCToCpp::OnScrollOffsetChanged(
CefRefPtr<CefBrowser> browser) {
if (CEF_MEMBER_MISSING(struct_, on_scroll_offset_changed))

View File

@ -50,6 +50,11 @@ class CefRenderHandlerCToCpp
int height) OVERRIDE;
virtual void OnCursorChange(CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor) OVERRIDE;
virtual bool StartDragging(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data, DragOperationsMask allowed_ops, int x,
int y) OVERRIDE;
virtual void UpdateDragCursor(CefRefPtr<CefBrowser> browser,
DragOperation operation) OVERRIDE;
virtual void OnScrollOffsetChanged(CefRefPtr<CefBrowser> browser) OVERRIDE;
};

View File

@ -0,0 +1,92 @@
// Copyright (c) 2014 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 "cefclient/bytes_write_handler.h"
#include "cefclient/util.h"
BytesWriteHandler::BytesWriteHandler(size_t grow)
: grow_(grow),
datasize_(grow),
offset_(0) {
ASSERT(grow > 0); // NOLINT(readability/check)
data_ = malloc(grow);
ASSERT(data_ != NULL);
}
BytesWriteHandler::~BytesWriteHandler() {
AutoLock lock_scope(this);
if (data_)
free(data_);
}
size_t BytesWriteHandler::Write(const void* ptr, size_t size, size_t n) {
AutoLock lock_scope(this);
size_t rv;
if (offset_ + static_cast<int64>(size * n) >= datasize_ &&
Grow(size * n) == 0) {
rv = 0;
} else {
memcpy(reinterpret_cast<char*>(data_) + offset_, ptr, size * n);
offset_ += size * n;
rv = n;
}
return rv;
}
int BytesWriteHandler::Seek(int64 offset, int whence) {
int rv = -1L;
AutoLock lock_scope(this);
switch (whence) {
case SEEK_CUR:
if (offset_ + offset > datasize_ || offset_ + offset < 0)
break;
offset_ += offset;
rv = 0;
break;
case SEEK_END: {
int64 offset_abs = abs(offset);
if (offset_abs > datasize_)
break;
offset_ = datasize_ - offset_abs;
rv = 0;
break;
}
case SEEK_SET:
if (offset > datasize_ || offset < 0)
break;
offset_ = offset;
rv = 0;
break;
}
return rv;
}
int64 BytesWriteHandler::Tell() {
AutoLock lock_scope(this);
return offset_;
}
int BytesWriteHandler::Flush() {
return 0;
}
size_t BytesWriteHandler::Grow(size_t size) {
AutoLock lock_scope(this);
size_t rv;
size_t s = (size > grow_ ? size : grow_);
void* tmp = realloc(data_, datasize_ + s);
ASSERT(tmp != NULL);
if (tmp) {
data_ = tmp;
datasize_ += s;
rv = datasize_;
} else {
rv = 0;
}
return rv;
}

View File

@ -0,0 +1,37 @@
// Copyright (c) 2014 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 CEF_TESTS_CEFCLIENT_BYTES_WRITE_HANDLER_H_
#define CEF_TESTS_CEFCLIENT_BYTES_WRITE_HANDLER_H_
#pragma once
#include "include/cef_stream.h"
class BytesWriteHandler : public CefWriteHandler {
public:
explicit BytesWriteHandler(size_t grow);
virtual ~BytesWriteHandler();
virtual size_t Write(const void* ptr, size_t size, size_t n) OVERRIDE;
virtual int Seek(int64 offset, int whence) OVERRIDE;
virtual int64 Tell() OVERRIDE;
virtual int Flush() OVERRIDE;
virtual bool MayBlock() OVERRIDE { return false; }
void* GetData() { return data_; }
int64 GetDataSize() { return offset_; }
protected:
size_t Grow(size_t size);
size_t grow_;
void* data_;
int64 datasize_;
int64 offset_;
IMPLEMENT_REFCOUNTING(BytesWriteHandler);
IMPLEMENT_LOCKING(BytesWriteHandler);
};
#endif // CEF_TESTS_CEFCLIENT_BYTES_WRITE_HANDLER_H_

View File

@ -0,0 +1,649 @@
// Copyright (c) 2014 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 "cefclient/cefclient_osr_dragdrop_win.h"
#include <shellapi.h>
#include <shlobj.h>
#include <windowsx.h>
#include <algorithm>
#include <string>
#include "include/cef_runnable.h"
#include "cefclient/bytes_write_handler.h"
#include "cefclient/cefclient_osr_widget_win.h"
#include "cefclient/resource.h"
#include "cefclient/util.h"
namespace {
DWORD DragOperationToDropEffect(CefRenderHandler::DragOperation allowed_ops) {
DWORD effect = DROPEFFECT_NONE;
if (allowed_ops & DRAG_OPERATION_COPY)
effect |= DROPEFFECT_COPY;
if (allowed_ops & DRAG_OPERATION_LINK)
effect |= DROPEFFECT_LINK;
if (allowed_ops & DRAG_OPERATION_MOVE)
effect |= DROPEFFECT_MOVE;
return effect;
}
CefRenderHandler::DragOperationsMask DropEffectToDragOperation(DWORD effect) {
DWORD operation = DRAG_OPERATION_NONE;
if (effect & DROPEFFECT_COPY)
operation |= DRAG_OPERATION_COPY;
if (effect & DROPEFFECT_LINK)
operation |= DRAG_OPERATION_LINK;
if (effect & DROPEFFECT_MOVE)
operation |= DRAG_OPERATION_MOVE;
return static_cast<CefRenderHandler::DragOperationsMask>(operation);
}
CefMouseEvent ToMouseEvent(POINTL p, DWORD key_state, HWND hWnd) {
CefMouseEvent ev;
POINT screen_point = { p.x, p.y };
ScreenToClient(hWnd, &screen_point);
ev.x = screen_point.x;
ev.y = screen_point.y;
ev.modifiers = OSRWindow::GetCefMouseModifiers(key_state);
return ev;
}
void GetStorageForBytes(STGMEDIUM* storage, const void* data, size_t bytes) {
HANDLE handle = GlobalAlloc(GPTR, static_cast<int>(bytes));
if (handle) {
memcpy(handle, data, bytes);
}
storage->hGlobal = handle;
storage->tymed = TYMED_HGLOBAL;
storage->pUnkForRelease = NULL;
}
template <typename T>
void GetStorageForString(STGMEDIUM* stgmed, const std::basic_string<T>& data) {
GetStorageForBytes(stgmed, data.c_str(),
(data.size() + 1) * sizeof(std::basic_string<T>::value_type));
}
void GetStorageForFileDescriptor(STGMEDIUM* storage,
const std::wstring& file_name) {
ASSERT(!file_name.empty());
HANDLE hdata = GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR));
FILEGROUPDESCRIPTOR* descriptor =
reinterpret_cast<FILEGROUPDESCRIPTOR*>(hdata);
descriptor->cItems = 1;
descriptor->fgd[0].dwFlags = FD_LINKUI;
wcsncpy_s(descriptor->fgd[0].cFileName, MAX_PATH, file_name.c_str(),
std::min(file_name.size(), static_cast<size_t>(MAX_PATH - 1u)));
storage->tymed = TYMED_HGLOBAL;
storage->hGlobal = hdata;
storage->pUnkForRelease = NULL;
}
// Helper method for converting from text/html to MS CF_HTML.
// Documentation for the CF_HTML format is available at
// http://msdn.microsoft.com/en-us/library/aa767917(VS.85).aspx
std::string HtmlToCFHtml(const std::string& html, const std::string& base_url) {
if (html.empty())
return std::string();
#define MAX_DIGITS 10
#define MAKE_NUMBER_FORMAT_1(digits) MAKE_NUMBER_FORMAT_2(digits)
#define MAKE_NUMBER_FORMAT_2(digits) "%0" #digits "u"
#define NUMBER_FORMAT MAKE_NUMBER_FORMAT_1(MAX_DIGITS)
static const char* header = "Version:0.9\r\n"
"StartHTML:" NUMBER_FORMAT "\r\n"
"EndHTML:" NUMBER_FORMAT "\r\n"
"StartFragment:" NUMBER_FORMAT "\r\n"
"EndFragment:" NUMBER_FORMAT "\r\n";
static const char* source_url_prefix = "SourceURL:";
static const char* start_markup = "<html>\r\n<body>\r\n<!--StartFragment-->";
static const char* end_markup = "<!--EndFragment-->\r\n</body>\r\n</html>";
// Calculate offsets
size_t start_html_offset = strlen(header) - strlen(NUMBER_FORMAT) * 4 +
MAX_DIGITS * 4;
if (!base_url.empty()) {
start_html_offset += strlen(source_url_prefix) + base_url.length()
+ 2; // Add 2 for \r\n.
}
size_t start_fragment_offset = start_html_offset + strlen(start_markup);
size_t end_fragment_offset = start_fragment_offset + html.length();
size_t end_html_offset = end_fragment_offset + strlen(end_markup);
char raw_result[1024];
_snprintf(raw_result, sizeof(1024),
header,
start_html_offset,
end_html_offset,
start_fragment_offset,
end_fragment_offset);
std::string result = raw_result;
if (!base_url.empty()) {
result.append(source_url_prefix);
result.append(base_url);
result.append("\r\n");
}
result.append(start_markup);
result.append(html);
result.append(end_markup);
#undef MAX_DIGITS
#undef MAKE_NUMBER_FORMAT_1
#undef MAKE_NUMBER_FORMAT_2
#undef NUMBER_FORMAT
return result;
}
void CFHtmlExtractMetadata(const std::string& cf_html,
std::string* base_url,
size_t* html_start,
size_t* fragment_start,
size_t* fragment_end) {
// Obtain base_url if present.
if (base_url) {
static std::string src_url_str("SourceURL:");
size_t line_start = cf_html.find(src_url_str);
if (line_start != std::string::npos) {
size_t src_end = cf_html.find("\n", line_start);
size_t src_start = line_start + src_url_str.length();
if (src_end != std::string::npos && src_start != std::string::npos) {
*base_url = cf_html.substr(src_start, src_end - src_start);
}
}
}
// Find the markup between "<!--StartFragment-->" and "<!--EndFragment-->".
// If the comments cannot be found, like copying from OpenOffice Writer,
// we simply fall back to using StartFragment/EndFragment bytecount values
// to determine the fragment indexes.
std::string cf_html_lower = cf_html;
size_t markup_start = cf_html_lower.find("<html", 0);
if (html_start) {
*html_start = markup_start;
}
size_t tag_start = cf_html.find("<!--StartFragment", markup_start);
if (tag_start == std::string::npos) {
static std::string start_fragment_str("StartFragment:");
size_t start_fragment_start = cf_html.find(start_fragment_str);
if (start_fragment_start != std::string::npos) {
*fragment_start = static_cast<size_t>(atoi(cf_html.c_str() +
start_fragment_start + start_fragment_str.length()));
}
static std::string end_fragment_str("EndFragment:");
size_t end_fragment_start = cf_html.find(end_fragment_str);
if (end_fragment_start != std::string::npos) {
*fragment_end = static_cast<size_t>(atoi(cf_html.c_str() +
end_fragment_start + end_fragment_str.length()));
}
} else {
*fragment_start = cf_html.find('>', tag_start) + 1;
size_t tag_end = cf_html.rfind("<!--EndFragment", std::string::npos);
*fragment_end = cf_html.rfind('<', tag_end);
}
}
void CFHtmlToHtml(const std::string& cf_html,
std::string* html,
std::string* base_url) {
size_t frag_start = std::string::npos;
size_t frag_end = std::string::npos;
CFHtmlExtractMetadata(cf_html, base_url, NULL, &frag_start, &frag_end);
if (html && frag_start != std::string::npos &&
frag_end != std::string::npos) {
*html = cf_html.substr(frag_start, frag_end - frag_start);
}
}
const DWORD moz_url_format = ::RegisterClipboardFormat(L"text/x-moz-url");
const DWORD html_format = ::RegisterClipboardFormat(L"HTML Format");
const DWORD file_desc_format =
::RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR);
const DWORD file_contents_format =
::RegisterClipboardFormat(CFSTR_FILECONTENTS);
bool DragDataToDataObject(CefRefPtr<CefDragData> drag_data,
IDataObject** data_object) {
const int kMaxDataObjects = 10;
FORMATETC fmtetcs[kMaxDataObjects];
STGMEDIUM stgmeds[kMaxDataObjects];
FORMATETC fmtetc = { 0, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
int curr_index = 0;
CefString text = drag_data->GetFragmentText();
if (!text.empty()) {
fmtetc.cfFormat = CF_UNICODETEXT;
fmtetcs[curr_index] = fmtetc;
GetStorageForString(&stgmeds[curr_index], text.ToWString());
curr_index++;
}
if (drag_data->IsLink() && !drag_data->GetLinkURL().empty()) {
std::wstring x_moz_url_str = drag_data->GetLinkURL().ToWString();
x_moz_url_str += '\n';
x_moz_url_str += drag_data->GetLinkTitle().ToWString();
fmtetc.cfFormat = moz_url_format;
fmtetcs[curr_index] = fmtetc;
GetStorageForString(&stgmeds[curr_index], x_moz_url_str);
curr_index++;
}
CefString html = drag_data->GetFragmentHtml();
if (!html.empty()) {
CefString base_url = drag_data->GetFragmentBaseURL();
std::string cfhtml = HtmlToCFHtml(html.ToString(), base_url.ToString());
fmtetc.cfFormat = html_format;
fmtetcs[curr_index] = fmtetc;
GetStorageForString(&stgmeds[curr_index], cfhtml);
curr_index++;
}
size_t bufferSize = drag_data->GetFileContents(NULL);
if (bufferSize) {
CefRefPtr<BytesWriteHandler> handler = new BytesWriteHandler(bufferSize);
CefRefPtr<CefStreamWriter> writer =
CefStreamWriter::CreateForHandler(handler.get());
drag_data->GetFileContents(writer);
ASSERT(handler->GetDataSize() == bufferSize);
CefString fileName = drag_data->GetFileName();
GetStorageForFileDescriptor(&stgmeds[curr_index], fileName.ToWString());
fmtetc.cfFormat = file_desc_format;
fmtetcs[curr_index] = fmtetc;
curr_index++;
GetStorageForBytes(&stgmeds[curr_index], handler->GetData(),
handler->GetDataSize());
fmtetc.cfFormat = file_contents_format;
fmtetcs[curr_index] = fmtetc;
curr_index++;
}
ASSERT(curr_index < kMaxDataObjects);
CComPtr<IDataObject> obj =
DataObjectWin::Create(fmtetcs, stgmeds, curr_index);
(*data_object) = obj.Detach();
return true;
}
CefRefPtr<CefDragData> DataObjectToDragData(IDataObject* data_object) {
CefRefPtr<CefDragData> drag_data = CefDragData::Create();
IEnumFORMATETC* enumFormats = NULL;
HRESULT res = data_object->EnumFormatEtc(DATADIR_GET, &enumFormats);
if (res != S_OK)
return drag_data;
enumFormats->Reset();
const int kCelt = 10;
ULONG celtFetched;
do {
celtFetched = kCelt;
FORMATETC rgelt[kCelt];
res = enumFormats->Next(kCelt, rgelt, &celtFetched);
for (unsigned i = 0; i < celtFetched; i++) {
CLIPFORMAT format = rgelt[i].cfFormat;
if (!(format == CF_UNICODETEXT ||
format == CF_TEXT ||
format == moz_url_format ||
format == html_format ||
format == CF_HDROP)
|| rgelt[i].tymed != TYMED_HGLOBAL)
continue;
STGMEDIUM medium;
if (data_object->GetData(&rgelt[i], &medium) == S_OK) {
if (!medium.hGlobal) {
ReleaseStgMedium(&medium);
continue;
}
void* hGlobal = GlobalLock(medium.hGlobal);
if (!hGlobal) {
ReleaseStgMedium(&medium);
continue;
}
if (format == CF_UNICODETEXT) {
CefString text;
text.FromWString((std::wstring::value_type*)hGlobal);
drag_data->SetFragmentText(text);
} else if (format == CF_TEXT) {
CefString text;
text.FromString((std::string::value_type*)hGlobal);
drag_data->SetFragmentText(text);
} else if (format == moz_url_format) {
std::wstring html((std::wstring::value_type*)hGlobal);
size_t pos = html.rfind('\n');
CefString url(html.substr(0, pos));
CefString title(html.substr(pos + 1));
drag_data->SetLinkURL(url);
drag_data->SetLinkTitle(title);
} else if (format == html_format) {
std::string cf_html((std::string::value_type*)hGlobal);
std::string base_url;
std::string html;
CFHtmlToHtml(cf_html, &html, &base_url);
drag_data->SetFragmentHtml(html);
drag_data->SetFragmentBaseURL(base_url);
}
if (format == CF_HDROP) {
HDROP hdrop = (HDROP)hGlobal;
const int kMaxFilenameLen = 4096;
const unsigned num_files = DragQueryFileW(hdrop, 0xffffffff, 0, 0);
for (unsigned int i = 0; i < num_files; ++i) {
wchar_t filename[kMaxFilenameLen];
if (!DragQueryFileW(hdrop, i, filename, kMaxFilenameLen))
continue;
WCHAR* name = wcsrchr(filename, '\\');
drag_data->AddFile(filename, (name ? name + 1 : filename));
}
}
if (medium.hGlobal)
GlobalUnlock(medium.hGlobal);
if (format == CF_HDROP)
DragFinish((HDROP)hGlobal);
else
ReleaseStgMedium(&medium);
}
}
} while (res == S_OK);
enumFormats->Release();
return drag_data;
}
} // namespace
CComPtr<DropTargetWin> DropTargetWin::Create(DragEvents* callback, HWND hWnd) {
return CComPtr<DropTargetWin>(new DropTargetWin(callback, hWnd));
}
HRESULT DropTargetWin::DragEnter(IDataObject* data_object,
DWORD key_state,
POINTL cursor_position,
DWORD* effect) {
if (!callback_)
return E_UNEXPECTED;
CefRefPtr<CefDragData> drag_data = current_drag_data_;
if (!drag_data) {
drag_data = DataObjectToDragData(data_object);
}
CefMouseEvent ev = ToMouseEvent(cursor_position, key_state, hWnd_);
CefBrowserHost::DragOperationsMask mask = DropEffectToDragOperation(*effect);
mask = callback_->OnDragEnter(drag_data, ev, mask);
*effect = DragOperationToDropEffect(mask);
return S_OK;
}
CefBrowserHost::DragOperationsMask DropTargetWin::StartDragging(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
CefRenderHandler::DragOperationsMask allowed_ops,
int x, int y) {
CComPtr<IDataObject> dataObject;
DWORD resEffect = DROPEFFECT_NONE;
if (DragDataToDataObject(drag_data, &dataObject)) {
CComPtr<IDropSource> dropSource = DropSourceWin::Create();
DWORD effect = DragOperationToDropEffect(allowed_ops);
current_drag_data_ = drag_data->Clone();
current_drag_data_->ResetFileContents();
HRESULT res = DoDragDrop(dataObject, dropSource, effect, &resEffect);
if (res != DRAGDROP_S_DROP)
resEffect = DROPEFFECT_NONE;
current_drag_data_ = NULL;
}
return DropEffectToDragOperation(resEffect);
}
HRESULT DropTargetWin::DragOver(DWORD key_state,
POINTL cursor_position,
DWORD* effect) {
if (!callback_)
return E_UNEXPECTED;
CefMouseEvent ev = ToMouseEvent(cursor_position, key_state, hWnd_);
CefBrowserHost::DragOperationsMask mask = DropEffectToDragOperation(*effect);
mask = callback_->OnDragOver(ev, mask);
*effect = DragOperationToDropEffect(mask);
return S_OK;
}
HRESULT DropTargetWin::DragLeave() {
if (!callback_)
return E_UNEXPECTED;
callback_->OnDragLeave();
return S_OK;
}
HRESULT DropTargetWin::Drop(IDataObject* data_object,
DWORD key_state,
POINTL cursor_position,
DWORD* effect) {
if (!callback_)
return E_UNEXPECTED;
CefMouseEvent ev = ToMouseEvent(cursor_position, key_state, hWnd_);
CefBrowserHost::DragOperationsMask mask = DropEffectToDragOperation(*effect);
mask = callback_->OnDrop(ev, mask);
*effect = DragOperationToDropEffect(mask);
return S_OK;
}
CComPtr<DropSourceWin> DropSourceWin::Create() {
return CComPtr<DropSourceWin>(new DropSourceWin());
}
HRESULT DropSourceWin::GiveFeedback(DWORD dwEffect) {
return DRAGDROP_S_USEDEFAULTCURSORS;
}
HRESULT DropSourceWin::QueryContinueDrag(BOOL fEscapePressed,
DWORD grfKeyState) {
if (fEscapePressed) {
return DRAGDROP_S_CANCEL;
}
if (!(grfKeyState & MK_LBUTTON)) {
return DRAGDROP_S_DROP;
}
return S_OK;
}
HRESULT DragEnumFormatEtc::CreateEnumFormatEtc(UINT cfmt,
FORMATETC* afmt,
IEnumFORMATETC** ppEnumFormatEtc) {
if (cfmt == 0 || afmt == 0 || ppEnumFormatEtc == 0)
return E_INVALIDARG;
*ppEnumFormatEtc = new DragEnumFormatEtc(afmt, cfmt);
return (*ppEnumFormatEtc) ? S_OK : E_OUTOFMEMORY;
}
HRESULT DragEnumFormatEtc::Next(ULONG celt,
FORMATETC* pFormatEtc,
ULONG* pceltFetched) {
ULONG copied = 0;
// copy the FORMATETC structures into the caller's buffer
while (m_nIndex < m_nNumFormats && copied < celt) {
DeepCopyFormatEtc(&pFormatEtc[copied], &m_pFormatEtc[m_nIndex]);
copied++;
m_nIndex++;
}
// store result
if (pceltFetched != 0)
*pceltFetched = copied;
// did we copy all that was requested?
return (copied == celt) ? S_OK : S_FALSE;
}
HRESULT DragEnumFormatEtc::Skip(ULONG celt) {
m_nIndex += celt;
return (m_nIndex <= m_nNumFormats) ? S_OK : S_FALSE;
}
HRESULT DragEnumFormatEtc::Reset(void) {
m_nIndex = 0;
return S_OK;
}
HRESULT DragEnumFormatEtc::Clone(IEnumFORMATETC** ppEnumFormatEtc) {
HRESULT hResult;
// make a duplicate enumerator
hResult = CreateEnumFormatEtc(m_nNumFormats, m_pFormatEtc, ppEnumFormatEtc);
if (hResult == S_OK) {
// manually set the index state
reinterpret_cast<DragEnumFormatEtc*>(*ppEnumFormatEtc)->m_nIndex = m_nIndex;
}
return hResult;
}
DragEnumFormatEtc::DragEnumFormatEtc(FORMATETC* pFormatEtc, int nNumFormats) {
AddRef();
m_nIndex = 0;
m_nNumFormats = nNumFormats;
m_pFormatEtc = new FORMATETC[nNumFormats];
// make a new copy of each FORMATETC structure
for (int i = 0; i < nNumFormats; i++) {
DeepCopyFormatEtc(&m_pFormatEtc[i], &pFormatEtc[i]);
}
}
DragEnumFormatEtc::~DragEnumFormatEtc() {
// first free any DVTARGETDEVICE structures
for (ULONG i = 0; i < m_nNumFormats; i++) {
if (m_pFormatEtc[i].ptd)
CoTaskMemFree(m_pFormatEtc[i].ptd);
}
// now free the main array
delete[] m_pFormatEtc;
}
void DragEnumFormatEtc::DeepCopyFormatEtc(FORMATETC* dest, FORMATETC* source) {
// copy the source FORMATETC into dest
*dest = *source;
if (source->ptd) {
// allocate memory for the DVTARGETDEVICE if necessary
dest->ptd = reinterpret_cast<DVTARGETDEVICE*>(
CoTaskMemAlloc(sizeof(DVTARGETDEVICE)));
// copy the contents of the source DVTARGETDEVICE into dest->ptd
*(dest->ptd) = *(source->ptd);
}
}
CComPtr<DataObjectWin> DataObjectWin::Create(FORMATETC* fmtetc,
STGMEDIUM* stgmed,
int count) {
return CComPtr<DataObjectWin>(new DataObjectWin(fmtetc, stgmed, count));
}
HRESULT DataObjectWin::GetDataHere(FORMATETC* pFormatEtc, STGMEDIUM* pmedium) {
return E_NOTIMPL;
}
HRESULT DataObjectWin::QueryGetData(FORMATETC* pFormatEtc) {
return (LookupFormatEtc(pFormatEtc) == -1) ? DV_E_FORMATETC : S_OK;
}
HRESULT DataObjectWin::GetCanonicalFormatEtc(FORMATETC* pFormatEct,
FORMATETC* pFormatEtcOut) {
pFormatEtcOut->ptd = NULL;
return E_NOTIMPL;
}
HRESULT DataObjectWin::SetData(FORMATETC* pFormatEtc,
STGMEDIUM* pMedium,
BOOL fRelease) {
return E_NOTIMPL;
}
HRESULT DataObjectWin::DAdvise(FORMATETC* pFormatEtc,
DWORD advf,
IAdviseSink*,
DWORD*) {
return E_NOTIMPL;
}
HRESULT DataObjectWin::DUnadvise(DWORD dwConnection) {
return E_NOTIMPL;
}
HRESULT DataObjectWin::EnumDAdvise(IEnumSTATDATA **ppEnumAdvise) {
return E_NOTIMPL;
}
HRESULT DataObjectWin::EnumFormatEtc(DWORD dwDirection,
IEnumFORMATETC** ppEnumFormatEtc) {
return DragEnumFormatEtc::CreateEnumFormatEtc(m_nNumFormats, m_pFormatEtc,
ppEnumFormatEtc);
}
HRESULT DataObjectWin::GetData(FORMATETC* pFormatEtc, STGMEDIUM* pMedium) {
int idx;
// try to match the specified FORMATETC with one of our supported formats
if ((idx = LookupFormatEtc(pFormatEtc)) == -1)
return DV_E_FORMATETC;
// found a match - transfer data into supplied storage medium
pMedium->tymed = m_pFormatEtc[idx].tymed;
pMedium->pUnkForRelease = 0;
// copy the data into the caller's storage medium
switch (m_pFormatEtc[idx].tymed) {
case TYMED_HGLOBAL:
pMedium->hGlobal = DupGlobalMem(m_pStgMedium[idx].hGlobal);
break;
default:
return DV_E_FORMATETC;
}
return S_OK;
}
HGLOBAL DataObjectWin::DupGlobalMem(HGLOBAL hMem) {
DWORD len = GlobalSize(hMem);
PVOID source = GlobalLock(hMem);
PVOID dest = GlobalAlloc(GMEM_FIXED, len);
memcpy(dest, source, len);
GlobalUnlock(hMem);
return dest;
}
int DataObjectWin::LookupFormatEtc(FORMATETC* pFormatEtc) {
// check each of our formats in turn to see if one matches
for (int i = 0; i < m_nNumFormats; i++) {
if ((m_pFormatEtc[i].tymed & pFormatEtc->tymed) &&
m_pFormatEtc[i].cfFormat == pFormatEtc->cfFormat &&
m_pFormatEtc[i].dwAspect == pFormatEtc->dwAspect) {
// return index of stored format
return i;
}
}
// error, format not found
return -1;
}
DataObjectWin::DataObjectWin(FORMATETC* fmtetc, STGMEDIUM* stgmed, int count)
: ref_count_(0) {
m_nNumFormats = count;
m_pFormatEtc = new FORMATETC[count];
m_pStgMedium = new STGMEDIUM[count];
for (int i = 0; i < count; i++) {
m_pFormatEtc[i] = fmtetc[i];
m_pStgMedium[i] = stgmed[i];
}
}

View File

@ -0,0 +1,178 @@
// Copyright (c) 2014 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 CEF_TESTS_CEFCLIENT_CEFCLIENT_OSR_DRAGDROP_WIN_H_
#define CEF_TESTS_CEFCLIENT_CEFCLIENT_OSR_DRAGDROP_WIN_H_
#pragma once
#include <atlcomcli.h>
#include <objidl.h>
#include <stdio.h>
#include "cefclient/dragdrop_events.h"
#define DEFAULT_QUERY_INTERFACE(__Class) \
HRESULT __stdcall QueryInterface(const IID& iid, void** object) { \
*object = NULL; \
if (IsEqualIID(iid, IID_IUnknown)) { \
IUnknown* obj = this; \
*object = obj; \
} else if (IsEqualIID(iid, IID_ ## __Class)) { \
__Class* obj = this; \
*object = obj; \
} else { \
return E_NOINTERFACE; \
} \
AddRef(); \
return S_OK; \
}
#define IUNKNOWN_IMPLEMENTATION \
ULONG __stdcall AddRef() { \
return ++ref_count_; \
} \
ULONG __stdcall Release() { \
if (--ref_count_ == 0) { \
delete this; \
return 0U; \
} \
return ref_count_; \
} \
protected: \
ULONG ref_count_;
class DropTargetWin : public IDropTarget {
public:
static CComPtr<DropTargetWin> Create(DragEvents* callback, HWND hWnd);
CefBrowserHost::DragOperationsMask StartDragging(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
CefRenderHandler::DragOperationsMask allowed_ops,
int x, int y);
// IDropTarget implementation:
HRESULT __stdcall DragEnter(IDataObject* data_object,
DWORD key_state,
POINTL cursor_position,
DWORD* effect);
HRESULT __stdcall DragOver(DWORD key_state,
POINTL cursor_position,
DWORD* effect);
HRESULT __stdcall DragLeave();
HRESULT __stdcall Drop(IDataObject* data_object,
DWORD key_state,
POINTL cursor_position,
DWORD* effect);
DEFAULT_QUERY_INTERFACE(IDropTarget)
IUNKNOWN_IMPLEMENTATION()
protected:
explicit DropTargetWin(DragEvents* callback, HWND hWnd) :
ref_count_(0),
callback_(callback),
hWnd_(hWnd) {}
virtual ~DropTargetWin() {}
private:
DragEvents* callback_;
HWND hWnd_;
CefRefPtr<CefDragData> current_drag_data_;
};
class DropSourceWin : public IDropSource {
public:
static CComPtr<DropSourceWin> Create();
// IDropSource implementation:
HRESULT __stdcall GiveFeedback(DWORD dwEffect);
HRESULT __stdcall QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState);
DEFAULT_QUERY_INTERFACE(IDropSource)
IUNKNOWN_IMPLEMENTATION()
protected:
explicit DropSourceWin() : ref_count_(0) {}
virtual ~DropSourceWin() {}
};
class DragEnumFormatEtc : public IEnumFORMATETC {
public:
static HRESULT CreateEnumFormatEtc(UINT cfmt,
FORMATETC* afmt,
IEnumFORMATETC** ppEnumFormatEtc);
//
// IEnumFormatEtc members
//
HRESULT __stdcall Next(ULONG celt,
FORMATETC * pFormatEtc,
ULONG * pceltFetched);
HRESULT __stdcall Skip(ULONG celt);
HRESULT __stdcall Reset(void);
HRESULT __stdcall Clone(IEnumFORMATETC ** ppEnumFormatEtc);
//
// Construction / Destruction
//
DragEnumFormatEtc(FORMATETC *pFormatEtc, int nNumFormats);
~DragEnumFormatEtc();
static void DeepCopyFormatEtc(FORMATETC *dest, FORMATETC *source);
DEFAULT_QUERY_INTERFACE(IEnumFORMATETC)
IUNKNOWN_IMPLEMENTATION()
private:
ULONG m_nIndex; // current enumerator index
ULONG m_nNumFormats; // number of FORMATETC members
FORMATETC* m_pFormatEtc; // array of FORMATETC objects
};
class DataObjectWin : public IDataObject {
public:
static CComPtr<DataObjectWin> Create(FORMATETC* fmtetc,
STGMEDIUM* stgmed,
int count);
// IDataObject memberS
HRESULT __stdcall GetDataHere(FORMATETC* pFormatEtc, STGMEDIUM *pmedium);
HRESULT __stdcall QueryGetData(FORMATETC* pFormatEtc);
HRESULT __stdcall GetCanonicalFormatEtc(FORMATETC* pFormatEct,
FORMATETC* pFormatEtcOut);
HRESULT __stdcall SetData(FORMATETC* pFormatEtc,
STGMEDIUM* pMedium,
BOOL fRelease);
HRESULT __stdcall DAdvise(FORMATETC* pFormatEtc,
DWORD advf,
IAdviseSink*,
DWORD*);
HRESULT __stdcall DUnadvise(DWORD dwConnection);
HRESULT __stdcall EnumDAdvise(IEnumSTATDATA **ppEnumAdvise);
HRESULT __stdcall EnumFormatEtc(DWORD dwDirection,
IEnumFORMATETC **ppEnumFormatEtc);
HRESULT __stdcall GetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium);
DEFAULT_QUERY_INTERFACE(IDataObject)
IUNKNOWN_IMPLEMENTATION()
protected:
int m_nNumFormats;
FORMATETC* m_pFormatEtc;
STGMEDIUM* m_pStgMedium;
static HGLOBAL DupGlobalMem(HGLOBAL hMem);
int LookupFormatEtc(FORMATETC *pFormatEtc);
explicit DataObjectWin(FORMATETC *fmtetc, STGMEDIUM *stgmed, int count);
};
#endif // CEF_TESTS_CEFCLIENT_CEFCLIENT_OSR_DRAGDROP_WIN_H_

View File

@ -19,7 +19,8 @@ class OSRBrowserProvider {
};
// The client OpenGL view.
@interface ClientOpenGLView : NSOpenGLView {
@interface ClientOpenGLView
: NSOpenGLView <NSDraggingSource, NSDraggingDestination> {
@public
NSTrackingArea* tracking_area_;
OSRBrowserProvider* browser_provider_;
@ -30,6 +31,13 @@ class OSRBrowserProvider {
bool was_last_mouse_down_on_view_;
// Drag and drop
CefRefPtr<CefDragData> current_drag_data_;
NSDragOperation current_drag_op_;
NSDragOperation current_allowed_ops_;
NSPasteboard* pasteboard_;
CFStringRef fileUTI_;
// Event monitor for scroll wheel end event.
id endWheelMonitor_;
}
@ -42,6 +50,8 @@ class OSRBrowserProvider {
- (BOOL)isKeyUpEvent:(NSEvent*)event;
- (BOOL)isKeyPadEvent:(NSEvent*)event;
- (CefRefPtr<CefBrowser>)getBrowser;
- (BOOL)startDragging:(CefRefPtr<CefDragData>)drag_data
allowed_ops:(NSDragOperation)ops point:(NSPoint)p;
@end
// Handler for off-screen rendering windows.
@ -84,6 +94,15 @@ class ClientOSRHandler : public ClientHandler::RenderHandler {
virtual void OnCursorChange(CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor) OVERRIDE;
virtual bool StartDragging(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
CefRenderHandler::DragOperationsMask allowed_ops,
int x, int y) OVERRIDE;
virtual void UpdateDragCursor(
CefRefPtr<CefBrowser> browser,
CefRenderHandler::DragOperation operation)OVERRIDE;
CefWindowHandle view() { return view_; }
private:

View File

@ -6,11 +6,15 @@
#import <objc/runtime.h>
#include <OpenGL/gl.h>
#include <vector>
#include "cefclient/cefclient_osr_widget_mac.h"
#include "include/cef_application_mac.h"
#include "include/cef_browser.h"
#include "include/cef_client.h"
#include "include/cef_url.h"
#include "cefclient/bytes_write_handler.h"
#include "cefclient/cefclient.h"
#include "cefclient/osrenderer.h"
#include "cefclient/resource_util.h"
@ -40,6 +44,11 @@ static BOOL SupportsBackingPropertiesChangedNotification() {
}
@interface ClientOpenGLView ()
- (void)resetDragDrop;
- (void)fillPasteboard;
- (void)populateDropData:(CefRefPtr<CefDragData>)data
fromPasteboard:(NSPasteboard*)pboard;
- (NSPoint)flipWindowPointToView:(const NSPoint&)windowPoint;
- (float)getDeviceScaleFactor;
- (void)windowDidChangeBackingProperties:(NSNotification*)notification;
@ -74,6 +83,9 @@ static CefRect convertRect(const NSRect& target, const NSRect& frame) {
rect.size.height);
}
static NSString* const kCEFDragDummyPboardType = @"org.CEF.drag-dummy-type";
static NSString* const kNSURLTitlePboardType = @"public.url-name";
} // namespace
ClientOSRHandler::ClientOSRHandler(ClientOpenGLView* view,
@ -274,6 +286,26 @@ void ClientOSRHandler::OnCursorChange(CefRefPtr<CefBrowser> browser,
[cursor set];
}
bool ClientOSRHandler::StartDragging(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
CefRenderHandler::DragOperationsMask allowed_ops,
int x, int y) {
REQUIRE_UI_THREAD();
if (!view_)
return false;
return [view_ startDragging:drag_data
allowed_ops:static_cast<NSDragOperation>(allowed_ops)
point:NSMakePoint(x, y)];
}
void ClientOSRHandler::UpdateDragCursor(CefRefPtr<CefBrowser> browser,
CefRenderHandler::DragOperation operation) {
REQUIRE_UI_THREAD();
if (!view_)
return;
view_->current_drag_op_ = operation;
}
void ClientOSRHandler::SetLoading(bool isLoading) {
}
@ -313,6 +345,16 @@ void ClientOSRHandler::SetLoading(bool isLoading) {
[self setWantsBestResolutionOpenGLSurface:YES];
}
[self resetDragDrop];
NSArray* types = [NSArray arrayWithObjects:
kCEFDragDummyPboardType,
NSStringPboardType,
NSFilenamesPboardType,
NSPasteboardTypeString,
nil];
[self registerForDraggedTypes:types];
return self;
}
@ -804,7 +846,318 @@ void ClientOSRHandler::SetLoading(bool isLoading) {
}
}
// Drag and drop
- (BOOL)startDragging:(CefRefPtr<CefDragData>)drag_data
allowed_ops:(NSDragOperation)ops
point:(NSPoint)position {
ASSERT(!pasteboard_);
ASSERT(!fileUTI_);
ASSERT(!current_drag_data_.get());
[self resetDragDrop];
current_allowed_ops_ = ops;
current_drag_data_ = drag_data;
[self fillPasteboard];
NSEvent* currentEvent = [NSApp currentEvent];
NSWindow* window = [self window];
NSTimeInterval eventTime = [currentEvent timestamp];
NSEvent* dragEvent = [NSEvent mouseEventWithType:NSLeftMouseDragged
location:position
modifierFlags:NSLeftMouseDraggedMask
timestamp:eventTime
windowNumber:[window windowNumber]
context:nil
eventNumber:0
clickCount:1
pressure:1.0];
[window dragImage:nil
at:position
offset:NSZeroSize
event:dragEvent
pasteboard:pasteboard_
source:self
slideBack:YES];
return YES;
}
// NSDraggingSource Protocol
- (NSDragOperation)draggingSession:(NSDraggingSession *)session
sourceOperationMaskForDraggingContext:(NSDraggingContext)context {
switch(context) {
case NSDraggingContextOutsideApplication:
return current_allowed_ops_;
case NSDraggingContextWithinApplication:
default:
return current_allowed_ops_;
}
}
- (NSArray*)namesOfPromisedFilesDroppedAtDestination:(NSURL*)dropDest {
if (![dropDest isFileURL])
return nil;
if (!current_drag_data_)
return nil;
size_t expected_size = current_drag_data_->GetFileContents(NULL);
if (expected_size == 0)
return nil;
std::string path = [[dropDest path] UTF8String];
path.append("/");
path.append(current_drag_data_->GetFileName().ToString());
CefRefPtr<CefStreamWriter> writer = CefStreamWriter::CreateForFile(path);
if (!writer)
return nil;
if (current_drag_data_->GetFileContents(writer) != expected_size)
return nil;
return @[ [NSString stringWithUTF8String:path.c_str()] ];
}
- (void)draggedImage:(NSImage*)anImage
endedAt:(NSPoint)screenPoint
operation:(NSDragOperation)operation {
if (operation == (NSDragOperationMove | NSDragOperationCopy))
operation &= ~NSDragOperationMove;
NSPoint windowPoint = [[self window] convertScreenToBase: screenPoint];
NSPoint pt = [self flipWindowPointToView:windowPoint];
CefRenderHandler::DragOperation op =
static_cast<CefRenderHandler::DragOperation>(operation);
browser_provider_->GetBrowser()->GetHost()->DragSourceEndedAt(pt.x, pt.y, op);
browser_provider_->GetBrowser()->GetHost()->DragSourceSystemDragEnded();
[self resetDragDrop];
}
// NSDraggingDestination Protocol
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)info {
CefRefPtr<CefDragData> drag_data;
if (!current_drag_data_) {
drag_data = CefDragData::Create();
[self populateDropData:drag_data
fromPasteboard:[info draggingPasteboard]];
} else {
drag_data = current_drag_data_->Clone();
drag_data->ResetFileContents();
}
NSPoint windowPoint = [info draggingLocation];
NSPoint viewPoint = [self flipWindowPointToView:windowPoint];
NSDragOperation mask = [info draggingSourceOperationMask];
CefMouseEvent ev;
ev.x = viewPoint.x;
ev.y = viewPoint.y;
ev.modifiers = [NSEvent modifierFlags];
CefBrowserHost::DragOperationsMask allowed_ops =
static_cast<CefBrowserHost::DragOperationsMask>(mask);
browser_provider_->GetBrowser()->GetHost()->DragTargetDragEnter(
drag_data, ev, allowed_ops);
browser_provider_->GetBrowser()->GetHost()->DragTargetDragOver(ev,
allowed_ops);
current_drag_op_ = NSDragOperationCopy;
return current_drag_op_;
}
- (void)draggingExited:(id <NSDraggingInfo>)sender {
browser_provider_->GetBrowser()->GetHost()->DragTargetDragLeave();
}
- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)info {
return YES;
}
- (BOOL)performDragOperation:(id <NSDraggingInfo>)info {
NSPoint windowPoint = [info draggingLocation];
NSPoint viewPoint = [self flipWindowPointToView:windowPoint];
CefMouseEvent ev;
ev.x = viewPoint.x;
ev.y = viewPoint.y;
ev.modifiers = [NSEvent modifierFlags];
browser_provider_->GetBrowser()->GetHost()->DragTargetDrop(ev);
return YES;
}
- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)info {
NSPoint windowPoint = [info draggingLocation];
NSPoint viewPoint = [self flipWindowPointToView:windowPoint];
NSDragOperation mask = [info draggingSourceOperationMask];
CefMouseEvent ev;
ev.x = viewPoint.x;
ev.y = viewPoint.y;
ev.modifiers = [NSEvent modifierFlags];
CefBrowserHost::DragOperationsMask allowed_ops =
static_cast<CefBrowserHost::DragOperationsMask>(mask);
browser_provider_->GetBrowser()->GetHost()->DragTargetDragOver(ev,
allowed_ops);
return current_drag_op_;
}
// NSPasteboardOwner Protocol
- (void)pasteboard:(NSPasteboard *)pboard provideDataForType:(NSString *)type {
if (!current_drag_data_) {
return;
}
// URL.
if ([type isEqualToString:NSURLPboardType]) {
ASSERT(current_drag_data_->IsLink());
NSString* strUrl = [NSString stringWithUTF8String:
current_drag_data_->GetLinkURL().ToString().c_str()];
NSURL* url = [NSURL URLWithString:strUrl];
[url writeToPasteboard:pboard];
// URL title.
} else if ([type isEqualToString:kNSURLTitlePboardType]) {
NSString* strTitle = [NSString stringWithUTF8String:
current_drag_data_->GetLinkTitle().ToString().c_str()];
[pboard setString:strTitle forType:kNSURLTitlePboardType];
// File contents.
} else if ([type isEqualToString:(NSString*)fileUTI_]) {
size_t size = current_drag_data_->GetFileContents(NULL);
ASSERT(size > 0);
CefRefPtr<BytesWriteHandler> handler = new BytesWriteHandler(size);
CefRefPtr<CefStreamWriter> writer =
CefStreamWriter::CreateForHandler(handler.get());
current_drag_data_->GetFileContents(writer);
ASSERT(handler->GetDataSize() == size);
[pboard setData:[NSData dataWithBytes:handler->GetData()
length:handler->GetDataSize()]
forType:(NSString*)fileUTI_];
// Plain text.
} else if ([type isEqualToString:NSStringPboardType]) {
NSString* strTitle = [NSString stringWithUTF8String:
current_drag_data_->GetFragmentText().ToString().c_str()];
[pboard setString:strTitle forType:NSStringPboardType];
} else if ([type isEqualToString:kCEFDragDummyPboardType]) {
// The dummy type _was_ promised and someone decided to call the bluff.
[pboard setData:[NSData data]
forType:kCEFDragDummyPboardType];
}
}
// Utility - private
- (void)resetDragDrop {
current_drag_op_ = NSDragOperationNone;
current_allowed_ops_ = NSDragOperationNone;
current_drag_data_ = NULL;
if (fileUTI_) {
CFRelease(fileUTI_);
fileUTI_ = NULL;
}
if (pasteboard_) {
[pasteboard_ release];
pasteboard_ = nil;
}
}
- (void)fillPasteboard {
ASSERT(!pasteboard_);
pasteboard_ = [[NSPasteboard pasteboardWithName:NSDragPboard] retain];
[pasteboard_ declareTypes:@[ kCEFDragDummyPboardType ]
owner:self];
// URL (and title).
if (current_drag_data_->IsLink()) {
[pasteboard_ addTypes:@[ NSURLPboardType, kNSURLTitlePboardType ]
owner:self];
}
// MIME type.
CefString mimeType;
size_t contents_size = current_drag_data_->GetFileContents(NULL);
CefString download_metadata = current_drag_data_->GetLinkMetadata();
CefString file_name = current_drag_data_->GetFileName();
// File.
if (contents_size > 0) {
std::string file_name = current_drag_data_->GetFileName().ToString();
size_t sep = file_name.find_last_of(".");
CefString extension = file_name.substr(sep + 1);
mimeType = CefGetMimeType(extension);
if (!mimeType.empty()) {
CFStringRef mimeTypeCF;
mimeTypeCF = CFStringCreateWithCString(kCFAllocatorDefault,
mimeType.ToString().c_str(), kCFStringEncodingUTF8);
fileUTI_ = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType,
mimeTypeCF, NULL);
CFRelease(mimeTypeCF);
// File (HFS) promise.
NSArray* fileUTIList = @[ (NSString*)fileUTI_ ];
[pasteboard_ addTypes:@[ NSFilesPromisePboardType ] owner:self];
[pasteboard_ setPropertyList:fileUTIList
forType:NSFilesPromisePboardType];
[pasteboard_ addTypes:fileUTIList owner:self];
}
}
// Plain text.
if (!current_drag_data_->GetFragmentText().empty()) {
[pasteboard_ addTypes:@[ NSStringPboardType ]
owner:self];
}
}
- (void)populateDropData:(CefRefPtr<CefDragData>)data
fromPasteboard:(NSPasteboard*)pboard {
ASSERT(data);
ASSERT(pboard);
ASSERT(data && !data->IsReadOnly());
NSArray* types = [pboard types];
// Get plain text.
if ([types containsObject:NSStringPboardType]) {
data->SetFragmentText(
[[pboard stringForType:NSStringPboardType] UTF8String]);
}
// Get files.
if ([types containsObject:NSFilenamesPboardType]) {
NSArray* files = [pboard propertyListForType:NSFilenamesPboardType];
if ([files isKindOfClass:[NSArray class]] && [files count]) {
for (NSUInteger i = 0; i < [files count]; i++) {
NSString* filename = [files objectAtIndex:i];
BOOL exists = [[NSFileManager defaultManager]
fileExistsAtPath:filename];
if (exists) {
data->AddFile([filename UTF8String], CefString());
}
}
}
}
}
- (NSPoint)flipWindowPointToView:(const NSPoint&)windowPoint {
NSPoint viewPoint = [self convertPoint:windowPoint fromView:nil];
NSRect viewFrame = [self frame];
viewPoint.y = viewFrame.size.height - viewPoint.y;
return viewPoint;
}
- (float)getDeviceScaleFactor {
float deviceScaleFactor = 1;
NSWindow* window = [self window];

View File

@ -44,6 +44,9 @@ bool OSRWindow::CreateWidget(HWND hWndParent, const RECT& rect,
// Reference released in OnDestroyed().
AddRef();
drop_target_ = DropTargetWin::Create(this, hWnd_);
HRESULT register_res = RegisterDragDrop(hWnd_, drop_target_);
ASSERT(register_res == S_OK);
return true;
}
@ -53,7 +56,10 @@ void OSRWindow::DestroyWidget() {
}
void OSRWindow::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
RevokeDragDrop(hWnd_);
drop_target_ = NULL;
DisableGL();
::DestroyWindow(hWnd_);
}
bool OSRWindow::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
@ -149,6 +155,29 @@ void OSRWindow::OnCursorChange(CefRefPtr<CefBrowser> browser,
SetCursor(cursor);
}
bool OSRWindow::StartDragging(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
CefRenderHandler::DragOperationsMask allowed_ops,
int x, int y) {
if (!drop_target_)
return false;
current_drag_op_ = DRAG_OPERATION_NONE;
CefBrowserHost::DragOperationsMask result =
drop_target_->StartDragging(browser, drag_data, allowed_ops, x, y);
current_drag_op_ = DRAG_OPERATION_NONE;
POINT pt = {};
GetCursorPos(&pt);
ScreenToClient(hWnd_, &pt);
browser->GetHost()->DragSourceEndedAt(pt.x, pt.y, result);
browser->GetHost()->DragSourceSystemDragEnded();
return true;
}
void OSRWindow::UpdateDragCursor(CefRefPtr<CefBrowser> browser,
CefRenderHandler::DragOperation operation) {
current_drag_op_ = operation;
}
void OSRWindow::Invalidate() {
if (!CefCurrentlyOn(TID_UI)) {
CefPostTask(TID_UI, NewCefRunnableMethod(this, &OSRWindow::Invalidate));
@ -167,6 +196,34 @@ void OSRWindow::Invalidate() {
kRenderDelay);
}
CefBrowserHost::DragOperationsMask
OSRWindow::OnDragEnter(CefRefPtr<CefDragData> drag_data,
CefMouseEvent ev,
CefBrowserHost::DragOperationsMask effect) {
browser_provider_->GetBrowser()->GetHost()->DragTargetDragEnter(
drag_data, ev, effect);
browser_provider_->GetBrowser()->GetHost()->DragTargetDragOver(ev, effect);
return current_drag_op_;
}
CefBrowserHost::DragOperationsMask OSRWindow::OnDragOver(CefMouseEvent ev,
CefBrowserHost::DragOperationsMask effect) {
browser_provider_->GetBrowser()->GetHost()->DragTargetDragOver(ev, effect);
return current_drag_op_;
}
void OSRWindow::OnDragLeave() {
browser_provider_->GetBrowser()->GetHost()->DragTargetDragLeave();
}
CefBrowserHost::DragOperationsMask
OSRWindow::OnDrop(CefMouseEvent ev,
CefBrowserHost::DragOperationsMask effect) {
browser_provider_->GetBrowser()->GetHost()->DragTargetDragOver(ev, effect);
browser_provider_->GetBrowser()->GetHost()->DragTargetDrop(ev);
return current_drag_op_;
}
OSRWindow::OSRWindow(OSRBrowserProvider* browser_provider, bool transparent)
: renderer_(transparent),
browser_provider_(browser_provider),
@ -174,7 +231,8 @@ OSRWindow::OSRWindow(OSRBrowserProvider* browser_provider, bool transparent)
hDC_(NULL),
hRC_(NULL),
painting_popup_(false),
render_task_pending_(false) {
render_task_pending_(false),
current_drag_op_(DRAG_OPERATION_NONE) {
}
OSRWindow::~OSRWindow() {

View File

@ -7,6 +7,7 @@
#pragma once
#include "include/cef_render_handler.h"
#include "cefclient/cefclient_osr_dragdrop_win.h"
#include "cefclient/client_handler.h"
#include "cefclient/osrenderer.h"
@ -18,7 +19,8 @@ class OSRBrowserProvider {
virtual ~OSRBrowserProvider() {}
};
class OSRWindow : public ClientHandler::RenderHandler {
class OSRWindow : public ClientHandler::RenderHandler,
public DragEvents {
public:
// Create a new OSRWindow instance. |browser_provider| must outlive this
// object.
@ -64,9 +66,31 @@ class OSRWindow : public ClientHandler::RenderHandler {
int height) OVERRIDE;
virtual void OnCursorChange(CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor) OVERRIDE;
virtual bool StartDragging(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
CefRenderHandler::DragOperationsMask allowed_ops,
int x, int y) OVERRIDE;
virtual void UpdateDragCursor(
CefRefPtr<CefBrowser> browser,
CefRenderHandler::DragOperation operation) OVERRIDE;
// DragEvents methods
virtual CefBrowserHost::DragOperationsMask OnDragEnter(
CefRefPtr<CefDragData> drag_data,
CefMouseEvent ev,
CefBrowserHost::DragOperationsMask effect) OVERRIDE;
virtual CefBrowserHost::DragOperationsMask OnDragOver(CefMouseEvent ev,
CefBrowserHost::DragOperationsMask effect) OVERRIDE;
virtual void OnDragLeave() OVERRIDE;
virtual CefBrowserHost::DragOperationsMask OnDrop(CefMouseEvent ev,
CefBrowserHost::DragOperationsMask effect) OVERRIDE;
void Invalidate();
static int GetCefKeyboardModifiers(WPARAM wparam, LPARAM lparam);
static int GetCefMouseModifiers(WPARAM wparam);
private:
OSRWindow(OSRBrowserProvider* browser_provider, bool transparent);
virtual ~OSRWindow();
@ -78,8 +102,6 @@ class OSRWindow : public ClientHandler::RenderHandler {
static ATOM RegisterOSRClass(HINSTANCE hInstance, LPCTSTR className);
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam);
static int GetCefKeyboardModifiers(WPARAM wparam, LPARAM lparam);
static int GetCefMouseModifiers(WPARAM wparam);
static bool isKeyDown(WPARAM wparam);
bool IsOverPopupWidget(int x, int y) const;
int GetPopupXOffset() const;
@ -92,6 +114,9 @@ class OSRWindow : public ClientHandler::RenderHandler {
HDC hDC_;
HGLRC hRC_;
CComPtr<DropTargetWin> drop_target_;
CefRenderHandler::DragOperation current_drag_op_;
bool painting_popup_;
bool render_task_pending_;

View File

@ -240,7 +240,7 @@ void ClientHandler::OnDownloadUpdated(
bool ClientHandler::OnDragEnter(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> dragData,
DragOperationsMask mask) {
CefDragHandler::DragOperationsMask mask) {
REQUIRE_UI_THREAD();
// Forbid dragging of link URLs.
@ -568,6 +568,22 @@ void ClientHandler::OnCursorChange(CefRefPtr<CefBrowser> browser,
m_OSRHandler->OnCursorChange(browser, cursor);
}
bool ClientHandler::StartDragging(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
CefRenderHandler::DragOperationsMask allowed_ops,
int x, int y) {
if (!m_OSRHandler.get())
return false;
return m_OSRHandler->StartDragging(browser, drag_data, allowed_ops, x, y);
}
void ClientHandler::UpdateDragCursor(CefRefPtr<CefBrowser> browser,
CefRenderHandler::DragOperation operation) {
if (!m_OSRHandler.get())
return;
m_OSRHandler->UpdateDragCursor(browser, operation);
}
void ClientHandler::SetMainHwnd(CefWindowHandle hwnd) {
AutoLock lock_scope(this);
m_MainHwnd = hwnd;

View File

@ -116,7 +116,7 @@ class ClientHandler : public CefClient,
// CefDragHandler methods
virtual bool OnDragEnter(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> dragData,
DragOperationsMask mask) OVERRIDE;
CefDragHandler::DragOperationsMask mask) OVERRIDE;
// CefGeolocationHandler methods
virtual void OnRequestGeolocationPermission(
@ -198,6 +198,13 @@ class ClientHandler : public CefClient,
int height) OVERRIDE;
virtual void OnCursorChange(CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor) OVERRIDE;
virtual bool StartDragging(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
CefRenderHandler::DragOperationsMask allowed_ops,
int x, int y) OVERRIDE;
virtual void UpdateDragCursor(CefRefPtr<CefBrowser> browser,
CefRenderHandler::DragOperation operation)
OVERRIDE;
void SetMainHwnd(CefWindowHandle hwnd);
CefWindowHandle GetMainHwnd() { return m_MainHwnd; }

View File

@ -0,0 +1,24 @@
// Copyright (c) 2014 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 CEF_TESTS_CEFCLIENT_DRAGDROP_EVENTS_H_
#define CEF_TESTS_CEFCLIENT_DRAGDROP_EVENTS_H_
#pragma once
#include "include/cef_render_handler.h"
#include "cefclient/client_handler.h"
class DragEvents {
public:
virtual CefBrowserHost::DragOperationsMask OnDragEnter(
CefRefPtr<CefDragData> drag_data,
CefMouseEvent ev,
CefBrowserHost::DragOperationsMask effect) = 0;
virtual CefBrowserHost::DragOperationsMask OnDragOver(CefMouseEvent ev,
CefBrowserHost::DragOperationsMask effect) = 0;
virtual void OnDragLeave() = 0;
virtual CefBrowserHost::DragOperationsMask OnDrop(CefMouseEvent ev,
CefBrowserHost::DragOperationsMask effect) = 0;
};
#endif // CEF_TESTS_CEFCLIENT_DRAGDROP_EVENTS_H_

View File

@ -6,6 +6,25 @@
body {background:rgba(255, 0, 0, 0.5); }
input {-webkit-appearance: none; }
#LI11select {width: 75px;}
.dropdiv {
width:50px;
height:50px;
border:1px solid #aaaaaa;
float: left;
}
#dragdiv {
width: 30px;
height: 30px;
background-color: green;
margin: 10px;
}
#draghere {
position: relative;
z-index: -1;
top: 7px;
left: 7px;
opacity: 0.4;
}
</style>
<script>
function getElement(id) { return document.getElementById(id); }
@ -24,9 +43,27 @@
param += event.button;
// Results in a call to the OnQuery method in os_rendering_unittest.cc.
window.testQuery({request: param});
if (window.testQuery)
window.testQuery({request: param});
}
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("Text",ev.target.id);
}
function drop(ev) {
var data=ev.dataTransfer.getData("Text");
ev.target.innerHTML = '';
var dragged = document.getElementById(data);
dragged.setAttribute('draggable', 'false');
ev.target.appendChild(dragged);
if (window.testQuery)
window.testQuery({request: "osrdrop"});
}
</script>
<body onfocus='onEventTest(event)' onblur='onEventTest(event)' onload='load();'>
<h1 id='LI00' onclick="onEventTest(event)">
@ -56,6 +93,12 @@
<li id='LI10' title='EXPECTED_TOOLTIP'>Mouse over this element will
trigger show a tooltip</li>
</ol>
<div class="dropdiv" id="dropdiv" ondrop="drop(event)" ondragover="allowDrop(event)">
<span id="draghere">Drag here</span>
</div>
<div class="dropdiv">
<div id="dragdiv" draggable="true" ondragstart="drag(event)"></div>
</div>
<br />
<br />
<br />

View File

@ -75,6 +75,8 @@ const CefRect kEditBoxRect(412, 245, 60, 22);
const CefRect kNavigateButtonRect(360, 271, 140, 22);
const CefRect kSelectRect(467, 22, 75, 20);
const CefRect kExpandedSelectRect(467, 42, 81, 322);
const CefRect kDropDivRect(8, 332, 52, 52);
const CefRect kDragDivRect(71, 342, 30, 30);
const int kDefaultVerticalScrollbarWidth = 17;
const int kVerticalScrollbarWidth = GetSystemMetrics(SM_CXVSCROLL);
const int kHorizontalScrollbarWidth = GetSystemMetrics(SM_CXHSCROLL);
@ -83,11 +85,15 @@ const CefRect kEditBoxRect(429, 228, 60, 25);
const CefRect kNavigateButtonRect(375, 251, 138, 28);
const CefRect kSelectRect(461, 21, 87, 26);
const CefRect kExpandedSelectRect(467, 42, 80, 262);
const CefRect kDropDivRect(8, 312, 52, 52);
const CefRect kDragDivRect(71, 324, 30, 30);
#elif defined(OS_LINUX)
const CefRect kEditBoxRect(434, 246, 60, 20);
const CefRect kNavigateButtonRect(380, 271, 140, 22);
const CefRect kSelectRect(467, 22, 75, 20);
const CefRect kExpandedSelectRect(467, 42, 79, 322);
const CefRect kDropDivRect(8, 332, 52, 52);
const CefRect kDragDivRect(71, 342, 30, 30);
const int kDefaultVerticalScrollbarWidth = 14;
const int kVerticalScrollbarWidth = 14;
const int kHorizontalScrollbarWidth = 14;
@ -187,6 +193,12 @@ enum OSRTestType {
OSR_TEST_POPUP_HIDE_ON_ESC,
// scrolling inside the popup should trigger repaint for popup area
OSR_TEST_POPUP_SCROLL_INSIDE,
// clicking and moving the mouse will call StartDragging
OSR_TEST_DRAG_DROP_START_DRAGGING,
// starting dragging over the drop region will call UpdateDragCursor
OSR_TEST_DRAG_DROP_UPDATE_CURSOR,
// dropping element inside drop region will move the element
OSR_TEST_DRAG_DROP_DROP,
};
// Used in the browser process.
@ -276,6 +288,10 @@ class OSRTestHandler : public RoutingTestHandler,
EXPECT_STREQ(messageStr.c_str(), "osrmousemove");
DestroySucceededTestSoon();
break;
case OSR_TEST_DRAG_DROP_DROP:
EXPECT_STREQ(messageStr.c_str(), "osrdrop");
DestroySucceededTestSoon();
break;
default:
// Intentionally left blank
break;
@ -304,7 +320,7 @@ class OSRTestHandler : public RoutingTestHandler,
CefRefPtr<CefRequest> request) OVERRIDE {
std::string url = request->GetURL();
if (url.find("http://tests/osrtest") == 0) {
if (url.find(kTestUrl) == 0) {
// Show the osr test contents
CefRefPtr<CefStreamReader> stream =
GetBinaryResourceReader("osr_test.html");
@ -426,18 +442,22 @@ class OSRTestHandler : public RoutingTestHandler,
// Send events after the first full repaint
switch (test_type_) {
case OSR_TEST_PAINT:
// test that we have a full repaint
EXPECT_EQ(dirtyRects.size(), 1U);
EXPECT_TRUE(IsFullRepaint(dirtyRects[0]));
EXPECT_EQ(*(reinterpret_cast<const uint32*>(buffer)), 0xffff8080);
DestroySucceededTestSoon();
if (StartTest()) {
// test that we have a full repaint
EXPECT_EQ(dirtyRects.size(), 1U);
EXPECT_TRUE(IsFullRepaint(dirtyRects[0]));
EXPECT_EQ(*(reinterpret_cast<const uint32*>(buffer)), 0xffff8080);
DestroySucceededTestSoon();
}
break;
case OSR_TEST_TRANSPARENCY:
// test that we have a full repaint
EXPECT_EQ(dirtyRects.size(), 1U);
EXPECT_TRUE(IsFullRepaint(dirtyRects[0]));
EXPECT_EQ(*(reinterpret_cast<const uint32*>(buffer)), 0x7f7f0000U);
DestroySucceededTestSoon();
if (StartTest()) {
// test that we have a full repaint
EXPECT_EQ(dirtyRects.size(), 1U);
EXPECT_TRUE(IsFullRepaint(dirtyRects[0]));
EXPECT_EQ(*(reinterpret_cast<const uint32*>(buffer)), 0x7f7f0000U);
DestroySucceededTestSoon();
}
break;
case OSR_TEST_FOCUS:
if (StartTest()) {
@ -629,17 +649,19 @@ class OSRTestHandler : public RoutingTestHandler,
// 1) vertical scrollbar
// 2) discovered new area (bottom side)
// 3) the whole visible rect.
EXPECT_EQ(dirtyRects.size(), 3U);
EXPECT_EQ(dirtyRects[0], CefRect(0, 0,
kOsrWidth - kVerticalScrollbarWidth, kHorizontalScrollbarWidth));
EXPECT_EQ(3U, dirtyRects.size());
if (dirtyRects.size() == 3U) {
EXPECT_EQ(dirtyRects[0], CefRect(0, 0,
kOsrWidth - kVerticalScrollbarWidth, kHorizontalScrollbarWidth));
EXPECT_EQ(dirtyRects[1], CefRect(0, kHorizontalScrollbarWidth,
kOsrWidth, kOsrHeight - 2 * kHorizontalScrollbarWidth));
EXPECT_EQ(dirtyRects[1], CefRect(0, kHorizontalScrollbarWidth,
kOsrWidth, kOsrHeight - 2 * kHorizontalScrollbarWidth));
EXPECT_EQ(dirtyRects[2],
CefRect(0, kOsrHeight - kHorizontalScrollbarWidth,
kOsrWidth - kVerticalScrollbarWidth,
kHorizontalScrollbarWidth));
EXPECT_EQ(dirtyRects[2],
CefRect(0, kOsrHeight - kHorizontalScrollbarWidth,
kOsrWidth - kVerticalScrollbarWidth,
kHorizontalScrollbarWidth));
}
#elif defined(OS_MACOSX)
// On Mac, when scrollbars are Always on, there is a single update of
// the whole view
@ -779,6 +801,29 @@ class OSRTestHandler : public RoutingTestHandler,
}
}
break;
case OSR_TEST_DRAG_DROP_START_DRAGGING:
case OSR_TEST_DRAG_DROP_UPDATE_CURSOR:
case OSR_TEST_DRAG_DROP_DROP:
{
// trigger the StartDragging event
if (StartTest()) {
// move the mouse over the element to drag
CefMouseEvent mouse_event;
mouse_event.x = MiddleX(kDragDivRect);
mouse_event.y = MiddleY(kDragDivRect);
mouse_event.modifiers = 0;
browser->GetHost()->SendMouseMoveEvent(mouse_event, false);
// click on the element to drag
mouse_event.modifiers = EVENTFLAG_LEFT_MOUSE_BUTTON;
browser->GetHost()->SendMouseClickEvent(mouse_event, MBT_LEFT,
false, 1);
// move the mouse to start dragging
mouse_event.x -= 5;
mouse_event.y -= 5;
browser->GetHost()->SendMouseMoveEvent(mouse_event, false);
}
}
break;
default:
break;
}
@ -791,6 +836,60 @@ class OSRTestHandler : public RoutingTestHandler,
}
}
virtual bool StartDragging(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
DragOperationsMask allowed_ops,
int x, int y) {
if (test_type_ == OSR_TEST_DRAG_DROP_START_DRAGGING && started()) {
DestroySucceededTestSoon();
return false;
} else if ((test_type_ == OSR_TEST_DRAG_DROP_UPDATE_CURSOR ||
test_type_ == OSR_TEST_DRAG_DROP_DROP) && started()) {
// place the mouse over the drop area to trigger UpdateDragCursor
CefRefPtr<CefDragData> data = drag_data->Clone();
data->ResetFileContents();
CefMouseEvent ev;
ev.x = MiddleX(kDragDivRect) - 5;
ev.y = MiddleY(kDragDivRect) - 5;
ev.modifiers = EVENTFLAG_LEFT_MOUSE_BUTTON;
browser->GetHost()->DragTargetDragEnter(data, ev, allowed_ops);
ev.x = MiddleX(kDropDivRect);
ev.y = MiddleY(kDropDivRect);
browser->GetHost()->SendMouseMoveEvent(ev, false);
browser->GetHost()->DragTargetDragOver(ev, allowed_ops);
ev.x += 5;
ev.y += 5;
browser->GetHost()->SendMouseMoveEvent(ev, false);
browser->GetHost()->DragTargetDragOver(ev, allowed_ops);
return true;
}
return false;
}
virtual void UpdateDragCursor(CefRefPtr<CefBrowser> browser,
DragOperation operation) {
if (test_type_ == OSR_TEST_DRAG_DROP_UPDATE_CURSOR && started()) {
if (operation != DRAG_OPERATION_NONE) {
browser->GetHost()->DragSourceEndedAt(MiddleX(kDropDivRect),
MiddleY(kDropDivRect),
DRAG_OPERATION_NONE);
browser->GetHost()->DragSourceSystemDragEnded();
DestroySucceededTestSoon();
}
} else if (test_type_ == OSR_TEST_DRAG_DROP_DROP && started()) {
CefMouseEvent ev;
ev.x = MiddleX(kDropDivRect);
ev.y = MiddleY(kDropDivRect);
ev.modifiers = 0;
browser->GetHost()->SendMouseClickEvent(ev, MBT_LEFT, true, 1);
browser->GetHost()->DragTargetDrop(ev);
browser->GetHost()->DragSourceEndedAt(ev.x, ev.y, operation);
browser->GetHost()->DragSourceSystemDragEnded();
}
}
virtual void OnScrollOffsetChanged(CefRefPtr<CefBrowser> browser) OVERRIDE {
if (test_type_ == OSR_TEST_SCROLLING && started()) {
DestroySucceededTestSoon();
@ -948,3 +1047,6 @@ OSR_TEST(PopupHideOnClick, OSR_TEST_POPUP_HIDE_ON_CLICK);
OSR_TEST(PopupHideOnScroll, OSR_TEST_POPUP_HIDE_ON_SCROLL);
OSR_TEST(PopupHideOnEsc, OSR_TEST_POPUP_HIDE_ON_ESC);
OSR_TEST(PopupScrollInside, OSR_TEST_POPUP_SCROLL_INSIDE);
OSR_TEST(DragDropStartDragging, OSR_TEST_DRAG_DROP_START_DRAGGING);
OSR_TEST(DragDropUpdateCursor, OSR_TEST_DRAG_DROP_UPDATE_CURSOR);
OSR_TEST(DragDropDropElement, OSR_TEST_DRAG_DROP_DROP);