From 998fa796ca69210baf0072e1141f9fc2c6e0d413 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Thu, 22 May 2014 16:11:26 +0000 Subject: [PATCH] Add off-screen drag & drop support (issue #1032). git-svn-id: https://chromiumembedded.googlecode.com/svn/branches/1916@1707 5089003a-bbd8-11dd-ad1f-f1f9622dbc98 --- cef_paths2.gypi | 5 + include/capi/cef_browser_capi.h | 65 ++ include/capi/cef_drag_data_capi.h | 75 ++ include/capi/cef_render_handler_capi.h | 26 + include/cef_browser.h | 68 ++ include/cef_drag_data.h | 78 +++ include/cef_render_handler.h | 32 + libcef/browser/browser_host_impl.cc | 204 +++++- libcef/browser/browser_host_impl.h | 9 + libcef/browser/web_contents_view_osr.cc | 46 +- libcef/browser/web_contents_view_osr.h | 1 + libcef/common/drag_data_impl.cc | 134 +++- libcef/common/drag_data_impl.h | 24 + libcef_dll/cpptoc/browser_host_cpptoc.cc | 124 ++++ libcef_dll/cpptoc/drag_data_cpptoc.cc | 185 +++++ libcef_dll/cpptoc/render_handler_cpptoc.cc | 52 ++ libcef_dll/ctocpp/browser_host_ctocpp.cc | 78 +++ libcef_dll/ctocpp/browser_host_ctocpp.h | 8 + libcef_dll/ctocpp/drag_data_ctocpp.cc | 163 +++++ libcef_dll/ctocpp/drag_data_ctocpp.h | 12 + libcef_dll/ctocpp/render_handler_ctocpp.cc | 48 ++ libcef_dll/ctocpp/render_handler_ctocpp.h | 5 + tests/cefclient/bytes_write_handler.cpp | 92 +++ tests/cefclient/bytes_write_handler.h | 37 + .../cefclient/cefclient_osr_dragdrop_win.cpp | 649 ++++++++++++++++++ tests/cefclient/cefclient_osr_dragdrop_win.h | 178 +++++ tests/cefclient/cefclient_osr_widget_mac.h | 21 +- tests/cefclient/cefclient_osr_widget_mac.mm | 353 ++++++++++ tests/cefclient/cefclient_osr_widget_win.cpp | 60 +- tests/cefclient/cefclient_osr_widget_win.h | 31 +- tests/cefclient/client_handler.cpp | 18 +- tests/cefclient/client_handler.h | 9 +- tests/cefclient/dragdrop_events.h | 24 + tests/cefclient/res/osr_test.html | 45 +- tests/unittests/os_rendering_unittest.cc | 142 +++- 35 files changed, 3061 insertions(+), 40 deletions(-) create mode 100644 tests/cefclient/bytes_write_handler.cpp create mode 100644 tests/cefclient/bytes_write_handler.h create mode 100644 tests/cefclient/cefclient_osr_dragdrop_win.cpp create mode 100644 tests/cefclient/cefclient_osr_dragdrop_win.h create mode 100644 tests/cefclient/dragdrop_events.h diff --git a/cef_paths2.gypi b/cef_paths2.gypi index 032b6cc01..c433afa7e 100644 --- a/cef_paths2.gypi +++ b/cef_paths2.gypi @@ -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', diff --git a/include/capi/cef_browser_capi.h b/include/capi/cef_browser_capi.h index 46eb1a715..611b4dadb 100644 --- a/include/capi/cef_browser_capi.h +++ b/include/capi/cef_browser_capi.h @@ -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; diff --git a/include/capi/cef_drag_data_capi.h b/include/capi/cef_drag_data_capi.h index 2182f67d4..383c67bd0 100644 --- a/include/capi/cef_drag_data_capi.h +++ b/include/capi/cef_drag_data_capi.h @@ -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 diff --git a/include/capi/cef_render_handler_capi.h b/include/capi/cef_render_handler_capi.h index 03ee32ab0..151292c8e 100644 --- a/include/capi/cef_render_handler_capi.h +++ b/include/capi/cef_render_handler_capi.h @@ -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. /// diff --git a/include/cef_browser.h b/include/cef_browser.h index 77d6651af..6214c4e4e 100644 --- a/include/cef_browser.h +++ b/include/cef_browser.h @@ -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 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_ diff --git a/include/cef_drag_data.h b/include/cef_drag_data.h index 58bcc3ed4..8f8094b44 100644 --- a/include/cef_drag_data.h +++ b/include/cef_drag_data.h @@ -39,6 +39,7 @@ #pragma once #include "include/cef_base.h" +#include "include/cef_stream.h" #include /// @@ -48,6 +49,24 @@ /*--cef(source=library)--*/ class CefDragData : public virtual CefBase { public: + /// + // Create a new CefDragData object. + /// + /*--cef()--*/ + static CefRefPtr Create(); + + /// + // Returns a copy of the current object. + /// + /*--cef()--*/ + virtual CefRefPtr 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 writer) =0; + /// // Retrieve the list of file names that are being dragged into the browser // window. /// /*--cef()--*/ virtual bool GetFileNames(std::vector& 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_ diff --git a/include/cef_render_handler.h b/include/cef_render_handler.h index c0997247f..aa4157f8d 100644 --- a/include/cef_render_handler.h +++ b/include/cef_render_handler.h @@ -40,6 +40,7 @@ #include "include/cef_base.h" #include "include/cef_browser.h" +#include "include/cef_drag_data.h" #include /// @@ -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 RectList; @@ -128,6 +131,35 @@ class CefRenderHandler : public virtual CefBase { virtual void OnCursorChange(CefRefPtr 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 browser, + CefRefPtr 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 browser, + DragOperation operation) {} + /// // Called when the scroll offset has changed. /// diff --git a/libcef/browser/browser_host_impl.cc b/libcef/browser/browser_host_impl.cc index 11e4674f2..30c1e4e55 100644 --- a/libcef/browser/browser_host_impl.cc +++ b/libcef/browser/browser_host_impl.cc @@ -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 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(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(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(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(op); + + rvh->DragSourceEndedAt(x, y, screenX, screenY, drag_op); +} + // content::WebContentsDelegate methods. // ----------------------------------------------------------------------------- @@ -1921,9 +2105,12 @@ bool CefBrowserHostImpl::CanDragEnter( blink::WebDragOperationsMask mask) { CefRefPtr handler = client_->GetDragHandler(); if (handler.get()) { - CefRefPtr drag_data(new CefDragDataImpl(data)); - if (handler->OnDragEnter(this, drag_data, - static_cast(mask))) { + CefRefPtr drag_data(new CefDragDataImpl(data)); + drag_data->SetReadOnly(true); + if (handler->OnDragEnter( + this, + drag_data.get(), + static_cast(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 unfocused_frame; CefRefPtr focused_frame; - + { base::AutoLock lock_scope(state_lock_); diff --git a/libcef/browser/browser_host_impl.h b/libcef/browser/browser_host_impl.h index b653b6062..8b95ff395 100644 --- a/libcef/browser/browser_host_impl.h +++ b/libcef/browser/browser_host_impl.h @@ -171,6 +171,15 @@ class CefBrowserHostImpl : public CefBrowserHost, OVERRIDE; virtual void HandleKeyEventAfterTextInputClient(CefEventHandle keyEvent) OVERRIDE; + virtual void DragTargetDragEnter(CefRefPtr 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 GetHost() OVERRIDE; diff --git a/libcef/browser/web_contents_view_osr.cc b/libcef/browser/web_contents_view_osr.cc index 03656c660..1c73e71f4 100644 --- a/libcef/browser/web_contents_view_osr.cc +++ b/libcef/browser/web_contents_view_osr.cc @@ -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 browser; + CefRefPtr handler; + bool handled = false; + CefRenderWidgetHostViewOSR* view = + static_cast(view_); + if (view) + browser = view->get_browser_impl(); + if (browser.get()) + handler = browser->GetClient()->GetRenderHandler(); + DCHECK(handler.get()); + if (handler.get()) { + CefRefPtr 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(allowed_ops), + event_info.event_location.x(), + event_info.event_location.y()); + } + if (!handled) + web_contents_->SystemDragEnded(); +} + +void CefWebContentsViewOSR::UpdateDragCursor( + blink::WebDragOperation operation) { + CefRefPtr browser; + CefRefPtr handler; + CefRenderWidgetHostViewOSR* view = + static_cast(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(operation)); + } } void CefWebContentsViewOSR::ShowPopupMenu( diff --git a/libcef/browser/web_contents_view_osr.h b/libcef/browser/web_contents_view_osr.h index 15da0958b..63cceae22 100644 --- a/libcef/browser/web_contents_view_osr.h +++ b/libcef/browser/web_contents_view_osr.h @@ -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, diff --git a/libcef/common/drag_data_impl.cc b/libcef/common/drag_data_impl.cc index 8251f5a37..20d570d05 100644 --- a/libcef/common/drag_data_impl.cc +++ b/libcef/common/drag_data_impl.cc @@ -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 + +#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::Create() { + return new CefDragDataImpl(); +} + +CefRefPtr 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 writer) { + AutoLock lock_scope(this); + if (data_.file_contents.empty()) + return 0; + + char* data = const_cast(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& names) { + AutoLock lock_scope(this); if (data_.filenames.empty()) return false; @@ -61,3 +132,62 @@ bool CefDragDataImpl::GetFileNames(std::vector& 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; +} diff --git a/libcef/common/drag_data_impl.h b/libcef/common/drag_data_impl.h index 17bbd1493..21717478d 100644 --- a/libcef/common/drag_data_impl.h +++ b/libcef/common/drag_data_impl.h @@ -14,7 +14,10 @@ // Implementation of CefDragData. class CefDragDataImpl : public CefDragData { public: + CefDragDataImpl(); explicit CefDragDataImpl(const content::DropData& data); + virtual CefRefPtr 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 writer); virtual bool GetFileNames(std::vector& 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_ diff --git a/libcef_dll/cpptoc/browser_host_cpptoc.cc b/libcef_dll/cpptoc/browser_host_cpptoc.cc index 04986c142..9c40da0e7 100644 --- a/libcef_dll/cpptoc/browser_host_cpptoc.cc +++ b/libcef_dll/cpptoc/browser_host_cpptoc.cc @@ -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 diff --git a/libcef_dll/cpptoc/drag_data_cpptoc.cc b/libcef_dll/cpptoc/drag_data_cpptoc.cc index e103948eb..c040fa15a 100644 --- a/libcef_dll/cpptoc/drag_data_cpptoc.cc +++ b/libcef_dll/cpptoc/drag_data_cpptoc.cc @@ -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 _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 _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(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 diff --git a/libcef_dll/cpptoc/render_handler_cpptoc.cc b/libcef_dll/cpptoc/render_handler_cpptoc.cc index 9d4d9df7b..60fe7383f 100644 --- a/libcef_dll/cpptoc/render_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/render_handler_cpptoc.cc @@ -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; } diff --git a/libcef_dll/ctocpp/browser_host_ctocpp.cc b/libcef_dll/ctocpp/browser_host_ctocpp.cc index 6a4f73eb4..23fc986bd 100644 --- a/libcef_dll/ctocpp/browser_host_ctocpp.cc +++ b/libcef_dll/ctocpp/browser_host_ctocpp.cc @@ -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 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 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 diff --git a/libcef_dll/ctocpp/drag_data_ctocpp.cc b/libcef_dll/ctocpp/drag_data_ctocpp.cc index 26c3adb36..34dab5fc9 100644 --- a/libcef_dll/ctocpp/drag_data_ctocpp.cc +++ b/libcef_dll/ctocpp/drag_data_ctocpp.cc @@ -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::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 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 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& names) { if (CEF_MEMBER_MISSING(struct_, get_file_names)) return false; @@ -187,6 +243,113 @@ bool CefDragDataCToCpp::GetFileNames(std::vector& 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 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 writer) OVERRIDE; virtual bool GetFileNames(std::vector& 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 diff --git a/libcef_dll/ctocpp/render_handler_ctocpp.cc b/libcef_dll/ctocpp/render_handler_ctocpp.cc index 276bff98f..f6c70cde0 100644 --- a/libcef_dll/ctocpp/render_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/render_handler_ctocpp.cc @@ -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 browser, cursor); } +bool CefRenderHandlerCToCpp::StartDragging(CefRefPtr browser, + CefRefPtr 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 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 browser) { if (CEF_MEMBER_MISSING(struct_, on_scroll_offset_changed)) diff --git a/libcef_dll/ctocpp/render_handler_ctocpp.h b/libcef_dll/ctocpp/render_handler_ctocpp.h index 2025a04ba..9d8b790e6 100644 --- a/libcef_dll/ctocpp/render_handler_ctocpp.h +++ b/libcef_dll/ctocpp/render_handler_ctocpp.h @@ -50,6 +50,11 @@ class CefRenderHandlerCToCpp int height) OVERRIDE; virtual void OnCursorChange(CefRefPtr browser, CefCursorHandle cursor) OVERRIDE; + virtual bool StartDragging(CefRefPtr browser, + CefRefPtr drag_data, DragOperationsMask allowed_ops, int x, + int y) OVERRIDE; + virtual void UpdateDragCursor(CefRefPtr browser, + DragOperation operation) OVERRIDE; virtual void OnScrollOffsetChanged(CefRefPtr browser) OVERRIDE; }; diff --git a/tests/cefclient/bytes_write_handler.cpp b/tests/cefclient/bytes_write_handler.cpp new file mode 100644 index 000000000..fb71cdd0e --- /dev/null +++ b/tests/cefclient/bytes_write_handler.cpp @@ -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(size * n) >= datasize_ && + Grow(size * n) == 0) { + rv = 0; + } else { + memcpy(reinterpret_cast(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; +} diff --git a/tests/cefclient/bytes_write_handler.h b/tests/cefclient/bytes_write_handler.h new file mode 100644 index 000000000..653fcc854 --- /dev/null +++ b/tests/cefclient/bytes_write_handler.h @@ -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_ diff --git a/tests/cefclient/cefclient_osr_dragdrop_win.cpp b/tests/cefclient/cefclient_osr_dragdrop_win.cpp new file mode 100644 index 000000000..7734994e9 --- /dev/null +++ b/tests/cefclient/cefclient_osr_dragdrop_win.cpp @@ -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 +#include +#include + +#include +#include + +#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(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(bytes)); + if (handle) { + memcpy(handle, data, bytes); + } + + storage->hGlobal = handle; + storage->tymed = TYMED_HGLOBAL; + storage->pUnkForRelease = NULL; +} + +template +void GetStorageForString(STGMEDIUM* stgmed, const std::basic_string& data) { + GetStorageForBytes(stgmed, data.c_str(), + (data.size() + 1) * sizeof(std::basic_string::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(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(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 = "\r\n\r\n"; + static const char* end_markup = "\r\n\r\n"; + + // 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 "" and "". + // 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("(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(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("