Rewrote the clipboard API to be more concurrent. Added a helper class to make it more foolproof. Updated all clients and unittests. Mac port by jeremy@chromium.org
Review URL: http://codereview.chromium.org/9154 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@4719 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
base
base.xcodeproj
base_lib.sconsbuild
clipboard.ccclipboard.hclipboard_linux.ccclipboard_mac.mmclipboard_unittest.ccclipboard_win.ccscoped_clipboard_writer.ccscoped_clipboard_writer.hchrome
browser
autocomplete
download
render_view_context_menu_controller.ccresource_message_filter.ccresource_message_filter.hcommon
renderer
views
webkit
build
glue
glue
port
platform
@ -170,7 +170,9 @@
|
||||
B52C916C0E9428F500208D01 /* clipboard_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B52C916B0E9428F500208D01 /* clipboard_unittest.cc */; };
|
||||
B53C85280E9C298C000F70AB /* idle_timer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 820EB4EB0E3A60FE009668FC /* idle_timer.cc */; };
|
||||
B57E4D780E9C26340090055D /* idletimer_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B57E4D770E9C26340090055D /* idletimer_unittest.cc */; };
|
||||
B5A8618E0EC1257900B332C2 /* clipboard.cc in Sources */ = {isa = PBXBuildFile; fileRef = B5A8618D0EC1257900B332C2 /* clipboard.cc */; };
|
||||
B5D544AB0EAFB7E000272A1C /* sys_string_conversions_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = B5D544AA0EAFB7E000272A1C /* sys_string_conversions_unittest.cc */; };
|
||||
B5E8F6CC0EBFB38E008DD1E9 /* scoped_clipboard_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = B5E8F6CB0EBFB38E008DD1E9 /* scoped_clipboard_writer.cc */; };
|
||||
B5EF235C0E89ABF500E1E114 /* platform_canvas_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = ABE1BA0C0E756EC4009041DA /* platform_canvas_unittest.cc */; };
|
||||
BA0F69870E79D7980079A8A1 /* thread_local_storage_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = BA0F69860E79D7980079A8A1 /* thread_local_storage_unittest.cc */; };
|
||||
BA5CC5840E788093004EDD45 /* shared_memory_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = BA5CC5830E788093004EDD45 /* shared_memory_unittest.cc */; };
|
||||
@ -630,7 +632,10 @@
|
||||
ABF68B280EB0F93100E72835 /* field_trial.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = field_trial.cc; sourceTree = "<group>"; };
|
||||
B52C916B0E9428F500208D01 /* clipboard_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clipboard_unittest.cc; sourceTree = "<group>"; };
|
||||
B57E4D770E9C26340090055D /* idletimer_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = idletimer_unittest.cc; sourceTree = "<group>"; };
|
||||
B5A8618D0EC1257900B332C2 /* clipboard.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clipboard.cc; sourceTree = "<group>"; };
|
||||
B5D544AA0EAFB7E000272A1C /* sys_string_conversions_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sys_string_conversions_unittest.cc; sourceTree = "<group>"; };
|
||||
B5E8F6CA0EBFB38E008DD1E9 /* scoped_clipboard_writer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scoped_clipboard_writer.h; sourceTree = "<group>"; };
|
||||
B5E8F6CB0EBFB38E008DD1E9 /* scoped_clipboard_writer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scoped_clipboard_writer.cc; sourceTree = "<group>"; };
|
||||
BA0F69860E79D7980079A8A1 /* thread_local_storage_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thread_local_storage_unittest.cc; sourceTree = "<group>"; };
|
||||
BA5CC5830E788093004EDD45 /* shared_memory_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shared_memory_unittest.cc; sourceTree = "<group>"; };
|
||||
BA739A000E5E3242009842A7 /* tracked_objects_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tracked_objects_unittest.cc; sourceTree = "<group>"; };
|
||||
@ -838,6 +843,7 @@
|
||||
825402D80D92D15E0006B936 /* blapit.h */,
|
||||
A5A0276B0E4BA33700498DA9 /* build_config.h */,
|
||||
7BD8F6D20E65DB0200034DE9 /* bzip2_error_handler.cc */,
|
||||
B5A8618D0EC1257900B332C2 /* clipboard.cc */,
|
||||
825402DB0D92D1730006B936 /* clipboard.h */,
|
||||
ABF4B99D0DC2BB6000A6E319 /* clipboard_mac.mm */,
|
||||
B52C916B0E9428F500208D01 /* clipboard_unittest.cc */,
|
||||
@ -968,6 +974,8 @@
|
||||
8254035F0D92D27C0006B936 /* revocable_store.h */,
|
||||
E49F1A5D0E4CD6E200386AEC /* run_all_unittests.cc */,
|
||||
7B5AD60D0D9DD8050012BCF1 /* scoped_cftyperef.h */,
|
||||
B5E8F6CB0EBFB38E008DD1E9 /* scoped_clipboard_writer.cc */,
|
||||
B5E8F6CA0EBFB38E008DD1E9 /* scoped_clipboard_writer.h */,
|
||||
7BA35DD10E8C0D5F0023C8B9 /* scoped_nsautorelease_pool.h */,
|
||||
7BA35DD20E8C0D5F0023C8B9 /* scoped_nsautorelease_pool.mm */,
|
||||
825403610D92D27C0006B936 /* scoped_ptr.h */,
|
||||
@ -1358,6 +1366,7 @@
|
||||
ABF4B98F0DC2BA6900A6E319 /* base_paths_mac.mm in Sources */,
|
||||
E45062A60E40A9BE0025A81A /* base_switches.cc in Sources */,
|
||||
7BD8F6D30E65DB0200034DE9 /* bzip2_error_handler.cc in Sources */,
|
||||
B5A8618E0EC1257900B332C2 /* clipboard.cc in Sources */,
|
||||
ABF4B99E0DC2BB6000A6E319 /* clipboard_mac.mm in Sources */,
|
||||
E48A05F70E3F61B300172919 /* command_line.cc in Sources */,
|
||||
824653680DC12CEC007C2BAA /* condition_variable_posix.cc in Sources */,
|
||||
@ -1397,6 +1406,7 @@
|
||||
4D11B59B0E91730200EF7617 /* rand_util_posix.cc in Sources */,
|
||||
7B836C050E55BBB800F6AD31 /* ref_counted.cc in Sources */,
|
||||
8246548C0DC259DB007C2BAA /* revocable_store.cc in Sources */,
|
||||
B5E8F6CC0EBFB38E008DD1E9 /* scoped_clipboard_writer.cc in Sources */,
|
||||
7BA35DD30E8C0D5F0023C8B9 /* scoped_nsautorelease_pool.mm in Sources */,
|
||||
ABF4B9BC0DC2BD1000A6E319 /* sha2.cc in Sources */,
|
||||
ABF4B9BE0DC2BD1500A6E319 /* sha512.cc in Sources */,
|
||||
|
@ -35,6 +35,7 @@ input_files = [
|
||||
'base_paths.cc',
|
||||
'base_switches.cc',
|
||||
'bzip2_error_handler.cc',
|
||||
'clipboard.cc',
|
||||
'clipboard_util.cc',
|
||||
'command_line.cc',
|
||||
'debug_util.cc',
|
||||
@ -63,6 +64,7 @@ input_files = [
|
||||
'ref_counted.cc',
|
||||
'resource_util.cc',
|
||||
'revocable_store.cc',
|
||||
'scoped_clipboard_writer.cc',
|
||||
'sha2.cc',
|
||||
'simple_thread.cc',
|
||||
'stats_table.cc',
|
||||
|
@ -205,6 +205,10 @@
|
||||
RelativePath="..\bzip2_error_handler.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\clipboard.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\clipboard.h"
|
||||
>
|
||||
@ -637,6 +641,14 @@
|
||||
RelativePath="..\revocable_store.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\scoped_clipboard_writer.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\scoped_clipboard_writer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\scoped_handle.h"
|
||||
>
|
||||
|
55
base/clipboard.cc
Normal file
55
base/clipboard.cc
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Many of these functions are based on those found in
|
||||
// webkit/port/platform/PasteboardWin.cpp
|
||||
|
||||
#include "base/clipboard.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
|
||||
void Clipboard::DispatchObject(ObjectType type, const ObjectMapParams& params) {
|
||||
switch (type) {
|
||||
case CBF_TEXT:
|
||||
WriteText(&(params[0].front()), params[0].size());
|
||||
break;
|
||||
|
||||
case CBF_HTML:
|
||||
if (params.size() == 2)
|
||||
WriteHTML(&(params[0].front()), params[0].size(),
|
||||
&(params[1].front()), params[1].size());
|
||||
else
|
||||
WriteHTML(&(params[0].front()), params[0].size(), NULL, 0);
|
||||
break;
|
||||
|
||||
#if defined(OS_WIN) || defined(OS_MACOSX)
|
||||
case CBF_BOOKMARK:
|
||||
WriteBookmark(&(params[0].front()), params[0].size(),
|
||||
&(params[1].front()), params[1].size());
|
||||
break;
|
||||
|
||||
case CBF_LINK:
|
||||
WriteHyperlink(&(params[0].front()), params[0].size(),
|
||||
&(params[1].front()), params[1].size());
|
||||
break;
|
||||
|
||||
case CBF_FILES:
|
||||
WriteFiles(&(params[0].front()), params[0].size());
|
||||
break;
|
||||
#endif // defined(OS_WIN) || defined(OS_MACOSX)
|
||||
|
||||
#if defined(OS_WIN)
|
||||
case CBF_WEBKIT:
|
||||
WriteWebSmartPaste();
|
||||
break;
|
||||
|
||||
case CBF_BITMAP:
|
||||
WriteBitmap(&(params[0].front()), &(params[1].front()));
|
||||
break;
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
default:
|
||||
NOTREACHED();
|
||||
}
|
||||
}
|
161
base/clipboard.h
161
base/clipboard.h
@ -31,58 +31,66 @@ class Clipboard {
|
||||
#elif defined(OS_LINUX)
|
||||
typedef struct _GdkAtom* FormatType;
|
||||
typedef struct _GtkClipboard GtkClipboard;
|
||||
// A mapping from target (format) string to the relevant data (usually a
|
||||
// string, but potentially arbitrary data).
|
||||
typedef std::map<std::string, std::pair<uint8*, size_t> > TargetMap;
|
||||
typedef std::map<std::string, std::pair<char*, size_t> > TargetMap;
|
||||
#endif
|
||||
|
||||
// ObjectType designates the type of data to be stored in the clipboard. This
|
||||
// designation is shared across all OSes. The system-specific designation
|
||||
// is defined by FormatType. A single ObjectType might be represented by
|
||||
// several system-specific FormatTypes. For example, on Linux the CBF_TEXT
|
||||
// ObjectType maps to "text/plain", "STRING", and several other formats. On
|
||||
// windows it maps to CF_UNICODETEXT.
|
||||
enum ObjectType {
|
||||
CBF_TEXT,
|
||||
CBF_HTML,
|
||||
CBF_BOOKMARK,
|
||||
CBF_LINK,
|
||||
CBF_FILES,
|
||||
CBF_WEBKIT,
|
||||
CBF_BITMAP,
|
||||
CBF_SMBITMAP // bitmap from shared memory
|
||||
};
|
||||
|
||||
// ObjectMap is a map from ObjectType to associated data.
|
||||
// The data is organized differently for each ObjectType. The following
|
||||
// table summarizes what kind of data is stored for each key.
|
||||
// * indicates an optional argument.
|
||||
//
|
||||
// Key Arguments Type
|
||||
// -------------------------------------
|
||||
// CBF_TEXT text char array
|
||||
// CBF_HTML html char array
|
||||
// url* char array
|
||||
// CBF_BOOKMARK html char array
|
||||
// url char array
|
||||
// CBF_LINK html char array
|
||||
// url char array
|
||||
// CBF_FILES files char array representing multiple files.
|
||||
// Filenames are separated by null characters and
|
||||
// the final filename is double null terminated.
|
||||
// CBF_WEBKIT none empty vector
|
||||
// CBF_BITMAP pixels byte array
|
||||
// size gfx::Size struct
|
||||
// CBF_SMBITMAP shared_mem shared memory handle
|
||||
// size gfx::Size struct
|
||||
typedef std::vector<char> ObjectMapParam;
|
||||
typedef std::vector<ObjectMapParam> ObjectMapParams;
|
||||
typedef std::map<int /* ObjectType */, ObjectMapParams> ObjectMap;
|
||||
|
||||
Clipboard();
|
||||
~Clipboard();
|
||||
|
||||
// Clears the clipboard. It is usually a good idea to clear the clipboard
|
||||
// before writing content to the clipboard.
|
||||
void Clear();
|
||||
// Write a bunch of objects to the system clipboard. Copies are made of the
|
||||
// contents of |objects|. On Windows they are copied to the system clipboard.
|
||||
// On linux they are copied into a structure owned by the Clipboard object and
|
||||
// kept until the system clipboard is set again.
|
||||
void WriteObjects(const ObjectMap& objects);
|
||||
|
||||
// Adds UNICODE and ASCII text to the clipboard.
|
||||
void WriteText(const std::wstring& text);
|
||||
|
||||
// Adds HTML to the clipboard. The url parameter is optional, but especially
|
||||
// useful if the HTML fragment contains relative links
|
||||
void WriteHTML(const std::wstring& markup, const std::string& src_url);
|
||||
|
||||
// Adds a bookmark to the clipboard
|
||||
void WriteBookmark(const std::wstring& title, const std::string& url);
|
||||
|
||||
// Adds both a bookmark and an HTML hyperlink to the clipboard. It is a
|
||||
// convenience wrapper around WriteBookmark and WriteHTML.
|
||||
void WriteHyperlink(const std::wstring& title, const std::string& url);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Adds a bitmap to the clipboard
|
||||
// This is the slowest way to copy a bitmap to the clipboard as we must first
|
||||
// memcpy the pixels into GDI and the blit the bitmap to the clipboard.
|
||||
// Pixel format is assumed to be 32-bit BI_RGB.
|
||||
void WriteBitmap(const void* pixels, const gfx::Size& size);
|
||||
|
||||
// Adds a bitmap to the clipboard
|
||||
// This function requires read and write access to the bitmap, but does not
|
||||
// actually modify the shared memory region.
|
||||
// Pixel format is assumed to be 32-bit BI_RGB.
|
||||
void WriteBitmapFromSharedMemory(const SharedMemory& bitmap,
|
||||
const gfx::Size& size);
|
||||
|
||||
// Adds a bitmap to the clipboard
|
||||
// This is the fastest way to copy a bitmap to the clipboard. The HBITMAP
|
||||
// may either be device-dependent or device-independent.
|
||||
void WriteBitmapFromHandle(HBITMAP hbitmap, const gfx::Size& size);
|
||||
|
||||
// Used by WebKit to determine whether WebKit wrote the clipboard last
|
||||
void WriteWebSmartPaste();
|
||||
#endif
|
||||
|
||||
// Adds a file or group of files to the clipboard.
|
||||
void WriteFile(const std::wstring& file);
|
||||
void WriteFiles(const std::vector<std::wstring>& files);
|
||||
// Behaves as above. If there is some shared memory handle passed as one of
|
||||
// the objects, it came from the process designated by |process|. This will
|
||||
// assist in turning it into a shared memory region that the current process
|
||||
// can use.
|
||||
void WriteObjects(const ObjectMap& objects, ProcessHandle process);
|
||||
|
||||
// Tests whether the clipboard contains a certain format
|
||||
bool IsFormatAvailable(FormatType format) const;
|
||||
@ -125,8 +133,42 @@ class Clipboard {
|
||||
#endif
|
||||
|
||||
private:
|
||||
void WriteText(const char* text_data, size_t text_len);
|
||||
|
||||
void WriteHTML(const char* markup_data,
|
||||
size_t markup_len,
|
||||
const char* url_data,
|
||||
size_t url_len);
|
||||
|
||||
void WriteBookmark(const char* title_data,
|
||||
size_t title_len,
|
||||
const char* url_data,
|
||||
size_t url_len);
|
||||
|
||||
void WriteHyperlink(const char* title_data,
|
||||
size_t title_len,
|
||||
const char* url_data,
|
||||
size_t url_len);
|
||||
|
||||
void WriteWebSmartPaste();
|
||||
|
||||
void WriteFiles(const char* file_data, size_t file_len);
|
||||
|
||||
void DispatchObject(ObjectType type, const ObjectMapParams& params);
|
||||
#if defined(OS_WIN)
|
||||
static void MarkupToHTMLClipboardFormat(const std::wstring& markup,
|
||||
void WriteBitmap(const char* pixel_data, const char* size_data);
|
||||
|
||||
void WriteBitmapFromSharedMemory(const char* bitmap_data,
|
||||
const char* size_data,
|
||||
ProcessHandle handle);
|
||||
|
||||
void WriteBitmapFromHandle(HBITMAP source_hbitmap,
|
||||
const gfx::Size& size);
|
||||
|
||||
// Safely write to system clipboard. Free |handle| on failure.
|
||||
void WriteToClipboard(FormatType format, HANDLE handle);
|
||||
|
||||
static void MarkupToHTMLClipboardFormat(const std::string& markup,
|
||||
const std::string& src_url,
|
||||
std::string* html_fragment);
|
||||
|
||||
@ -138,25 +180,26 @@ class Clipboard {
|
||||
std::wstring* title,
|
||||
std::string* url);
|
||||
|
||||
// Free a handle depending on its type (as intuited from format)
|
||||
static void FreeData(FormatType format, HANDLE data);
|
||||
|
||||
HWND clipboard_owner_;
|
||||
#elif defined(OS_LINUX)
|
||||
// Data is stored in the |clipboard_data_| map until it is saved to the system
|
||||
// clipboard. The Store* functions save data to the |clipboard_data_| map. The
|
||||
// SetGtkClipboard function replaces whatever is on the system clipboard with
|
||||
// the contents of |clipboard_data_|.
|
||||
// The Write* functions make a deep copy of the data passed to them an store
|
||||
// it in |clipboard_data_|.
|
||||
|
||||
// Write changes to gtk clipboard.
|
||||
void SetGtkClipboard();
|
||||
// Free pointers in clipboard_data_ and clear() the map.
|
||||
void FreeTargetMap();
|
||||
// Insert a mapping into clipboard_data_, or change an existing mapping.
|
||||
uint8* InsertOrOverwrite(std::string target, uint8* data, size_t data_len);
|
||||
// Insert a mapping into clipboard_data_.
|
||||
void InsertMapping(const char* key, char* data, size_t data_len);
|
||||
|
||||
// We have to be able to store multiple formats on the clipboard
|
||||
// simultaneously. The Chrome Clipboard class accomplishes this by
|
||||
// expecting that consecutive calls to Write* (WriteHTML, WriteText, etc.)
|
||||
// The GTK clipboard interface does not naturally support consecutive calls
|
||||
// building on one another. So we keep all data in a map, and always pass the
|
||||
// map when we are setting the gtk clipboard. Consecutive calls to Write*
|
||||
// will write to the map and set the GTK clipboard, then add to the same
|
||||
// map and set the GTK clipboard again. GTK thinks it is wiping out the
|
||||
// clipboard but we are actually keeping the previous data.
|
||||
TargetMap clipboard_data_;
|
||||
TargetMap* clipboard_data_;
|
||||
GtkClipboard* clipboard_;
|
||||
#endif
|
||||
|
||||
|
@ -32,18 +32,44 @@ void GetData(GtkClipboard* clipboard,
|
||||
return;
|
||||
|
||||
gtk_selection_data_set(selection_data, selection_data->target, 8,
|
||||
iter->second.first,
|
||||
reinterpret_cast<guchar*>(iter->second.first),
|
||||
iter->second.second);
|
||||
}
|
||||
|
||||
// GtkClipboardClearFunc callback.
|
||||
// GTK will call this when new data is set on the clipboard (whether or not we
|
||||
// retain ownership) or when gtk_clipboard_clear() is called. We don't do
|
||||
// anything because we don't want to clear the clipboard_data_ map if we call
|
||||
// set data several times in a row. Instead we manually clear the
|
||||
// clipboard_data_ map on Clear() and on Clipboard destruction.
|
||||
// We are guaranteed this will be called exactly once for each call to
|
||||
// gtk_clipboard_set_with_data
|
||||
void ClearData(GtkClipboard* clipboard,
|
||||
gpointer user_data) {
|
||||
Clipboard::TargetMap* map =
|
||||
reinterpret_cast<Clipboard::TargetMap*>(user_data);
|
||||
std::set<char*> ptrs;
|
||||
|
||||
for (Clipboard::TargetMap::iterator iter = map->begin();
|
||||
iter != map->end(); ++iter)
|
||||
ptrs.insert(iter->second.first);
|
||||
|
||||
for (std::set<char*>::iterator iter = ptrs.begin();
|
||||
iter != ptrs.end(); ++iter)
|
||||
delete[] *iter;
|
||||
|
||||
delete map;
|
||||
}
|
||||
|
||||
// Frees the pointers in the given map and clears the map.
|
||||
// Does not double-free any pointers.
|
||||
void FreeTargetMap(Clipboard::TargetMap map) {
|
||||
std::set<char*> ptrs;
|
||||
|
||||
for (Clipboard::TargetMap::iterator iter = map.begin();
|
||||
iter != map.end(); ++iter)
|
||||
ptrs.insert(iter->second.first);
|
||||
|
||||
for (std::set<char*>::iterator iter = ptrs.begin();
|
||||
iter != ptrs.end(); ++iter)
|
||||
delete[] *iter;
|
||||
|
||||
map.clear();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -56,46 +82,62 @@ Clipboard::~Clipboard() {
|
||||
// TODO(estade): do we want to save clipboard data after we exit?
|
||||
// gtk_clipboard_set_can_store and gtk_clipboard_store work
|
||||
// but have strangely awful performance.
|
||||
Clear();
|
||||
}
|
||||
|
||||
void Clipboard::Clear() {
|
||||
gtk_clipboard_clear(clipboard_);
|
||||
FreeTargetMap();
|
||||
}
|
||||
void Clipboard::WriteObjects(const ObjectMap& objects) {
|
||||
clipboard_data_ = new TargetMap();
|
||||
|
||||
void Clipboard::WriteText(const std::wstring& text) {
|
||||
std::string utf8_text = WideToUTF8(text);
|
||||
size_t text_len = utf8_text.size() + 1;
|
||||
uint8* text_data = new uint8[text_len];
|
||||
memcpy(text_data, utf8_text.c_str(), text_len);
|
||||
for (ObjectMap::const_iterator iter = objects.begin();
|
||||
iter != objects.end(); ++iter) {
|
||||
DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
|
||||
}
|
||||
|
||||
uint8* old_data = InsertOrOverwrite(kMimeText, text_data, text_len);
|
||||
InsertOrOverwrite("TEXT", text_data, text_len);
|
||||
InsertOrOverwrite("STRING", text_data, text_len);
|
||||
InsertOrOverwrite("UTF8_STRING", text_data, text_len);
|
||||
InsertOrOverwrite("COMPOUND_TEXT", text_data, text_len);
|
||||
|
||||
if (old_data)
|
||||
delete[] old_data;
|
||||
|
||||
SetGtkClipboard();
|
||||
}
|
||||
|
||||
void Clipboard::WriteHTML(const std::wstring& markup,
|
||||
const std::string& src_url) {
|
||||
// TODO(estade): might not want to ignore src_url
|
||||
std::string html = WideToUTF8(markup);
|
||||
size_t data_len = html.size() + 1;
|
||||
uint8* html_data = new uint8[data_len];
|
||||
memcpy(html_data, html.c_str(), data_len);
|
||||
// Take ownership of the GTK clipboard and inform it of the targets we support.
|
||||
void Clipboard::SetGtkClipboard() {
|
||||
GtkTargetEntry targets[clipboard_data_->size()];
|
||||
|
||||
uint8* old_data = InsertOrOverwrite(kMimeHtml, html_data, data_len);
|
||||
int i = 0;
|
||||
for (Clipboard::TargetMap::iterator iter = clipboard_data_->begin();
|
||||
iter != clipboard_data_->end(); ++iter, ++i) {
|
||||
char* target_string = new char[iter->first.size() + 1];
|
||||
strcpy(target_string, iter->first.c_str());
|
||||
targets[i].target = target_string;
|
||||
targets[i].flags = 0;
|
||||
targets[i].info = i;
|
||||
}
|
||||
|
||||
if (old_data)
|
||||
delete[] old_data;
|
||||
gtk_clipboard_set_with_data(clipboard_, targets,
|
||||
clipboard_data_->size(),
|
||||
GetData, ClearData,
|
||||
clipboard_data_);
|
||||
|
||||
SetGtkClipboard();
|
||||
for (size_t i = 0; i < clipboard_data_->size(); i++)
|
||||
delete[] targets[i].target;
|
||||
}
|
||||
|
||||
void Clipboard::WriteText(const char* text_data, size_t text_len) {
|
||||
char* data = new char[text_len];
|
||||
memcpy(data, text_data, text_len);
|
||||
|
||||
InsertMapping(kMimeText, data, text_len);
|
||||
InsertMapping("TEXT", data, text_len);
|
||||
InsertMapping("STRING", data, text_len);
|
||||
InsertMapping("UTF8_STRING", data, text_len);
|
||||
InsertMapping("COMPOUND_TEXT", data, text_len);
|
||||
}
|
||||
|
||||
void Clipboard::WriteHTML(const char* markup_data,
|
||||
size_t markup_len,
|
||||
const char* url_data,
|
||||
size_t url_len) {
|
||||
// TODO(estade): might not want to ignore |url_data|
|
||||
char* data = new char[markup_len];
|
||||
memcpy(data, markup_data, markup_len);
|
||||
|
||||
InsertMapping(kMimeHtml, data, markup_len);
|
||||
}
|
||||
|
||||
// We do not use gtk_clipboard_wait_is_target_available because of
|
||||
@ -185,62 +227,18 @@ Clipboard::FormatType Clipboard::GetHtmlFormatType() {
|
||||
return gdk_atom_intern(kMimeHtml, false);
|
||||
}
|
||||
|
||||
// Take ownership of the GTK clipboard and inform it of the targets we support.
|
||||
void Clipboard::SetGtkClipboard() {
|
||||
GtkTargetEntry targets[clipboard_data_.size()];
|
||||
// Insert the key/value pair in the clipboard_data structure. If
|
||||
// the mapping already exists, it frees the associated data. Don't worry
|
||||
// about double freeing because if the same key is inserted into the
|
||||
// map twice, it must have come from different Write* functions and the
|
||||
// data pointer cannot be the same.
|
||||
void Clipboard::InsertMapping(const char* key,
|
||||
char* data,
|
||||
size_t data_len) {
|
||||
TargetMap::iterator iter = clipboard_data_->find(key);
|
||||
|
||||
int i = 0;
|
||||
for (Clipboard::TargetMap::iterator iter = clipboard_data_.begin();
|
||||
iter != clipboard_data_.end(); iter++, i++) {
|
||||
char* target_string = new char[iter->first.size() + 1];
|
||||
strcpy(target_string, iter->first.c_str());
|
||||
targets[i].target = target_string;
|
||||
targets[i].flags = 0;
|
||||
targets[i].info = i;
|
||||
}
|
||||
if (iter != clipboard_data_->end())
|
||||
delete[] iter->second.first;
|
||||
|
||||
gtk_clipboard_set_with_data(clipboard_, targets,
|
||||
clipboard_data_.size(),
|
||||
GetData, ClearData,
|
||||
&clipboard_data_);
|
||||
|
||||
for (size_t i = 0; i < clipboard_data_.size(); i++)
|
||||
delete[] targets[i].target;
|
||||
(*clipboard_data_)[key] = std::make_pair(data, data_len);
|
||||
}
|
||||
|
||||
// Free the pointers in the clipboard_data_ map and reset the map.
|
||||
void Clipboard::FreeTargetMap() {
|
||||
std::set<uint8*> ptrs;
|
||||
|
||||
for (Clipboard::TargetMap::iterator iter = clipboard_data_.begin();
|
||||
iter != clipboard_data_.end(); iter++)
|
||||
ptrs.insert(iter->second.first);
|
||||
|
||||
for (std::set<uint8*>::iterator iter = ptrs.begin();
|
||||
iter != ptrs.end(); iter++)
|
||||
delete[] *iter;
|
||||
|
||||
clipboard_data_.clear();
|
||||
}
|
||||
|
||||
// Insert the key/value pair in the clipboard_data structure. Overwrite
|
||||
// and any old value that might have had that key. If we overwrote something,
|
||||
// return the pointer to that something. Otherwise return null.
|
||||
uint8* Clipboard::InsertOrOverwrite(std::string key,
|
||||
uint8* data, size_t data_len) {
|
||||
std::pair<std::string, std::pair<uint8*, size_t> > mapping =
|
||||
std::make_pair(key, std::make_pair(data, data_len));
|
||||
|
||||
Clipboard::TargetMap::iterator iter = clipboard_data_.find(key);
|
||||
uint8* retval = NULL;
|
||||
|
||||
if (iter == clipboard_data_.end()) {
|
||||
clipboard_data_.insert(mapping);
|
||||
} else {
|
||||
retval = iter->second.first;
|
||||
iter->second = mapping.second;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -32,39 +32,59 @@ Clipboard::Clipboard() {
|
||||
Clipboard::~Clipboard() {
|
||||
}
|
||||
|
||||
void Clipboard::Clear() {
|
||||
void Clipboard::WriteObjects(const ObjectMap& objects) {
|
||||
NSPasteboard* pb = GetPasteboard();
|
||||
[pb declareTypes:[NSArray array] owner:nil];
|
||||
|
||||
for (ObjectMap::const_iterator iter = objects.begin();
|
||||
iter != objects.end(); ++iter) {
|
||||
DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Clipboard::WriteText(const std::wstring& text) {
|
||||
void Clipboard::WriteText(const char* text_data, size_t text_len) {
|
||||
std::string text_str(text_data, text_len);
|
||||
NSString *text = base::SysUTF8ToNSString(text_str);
|
||||
NSPasteboard* pb = GetPasteboard();
|
||||
[pb addTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
|
||||
[pb setString:base::SysWideToNSString(text) forType:NSStringPboardType];
|
||||
[pb setString:text forType:NSStringPboardType];
|
||||
}
|
||||
|
||||
void Clipboard::WriteHTML(const std::wstring& markup,
|
||||
const std::string& src_url) {
|
||||
// TODO(avi): src_url?
|
||||
void Clipboard::WriteHTML(const char* markup_data,
|
||||
size_t markup_len,
|
||||
const char* url_data,
|
||||
size_t url_len) {
|
||||
std::string html_fragment_str(markup_data, markup_len);
|
||||
NSString *html_fragment = base::SysUTF8ToNSString(html_fragment_str);
|
||||
|
||||
// TODO(avi): url_data?
|
||||
NSPasteboard* pb = GetPasteboard();
|
||||
[pb addTypes:[NSArray arrayWithObject:NSHTMLPboardType] owner:nil];
|
||||
[pb setString:base::SysWideToNSString(markup) forType:NSHTMLPboardType];
|
||||
[pb setString:html_fragment forType:NSHTMLPboardType];
|
||||
}
|
||||
|
||||
void Clipboard::WriteBookmark(const std::wstring& title,
|
||||
const std::string& url) {
|
||||
WriteHyperlink(title, url);
|
||||
void Clipboard::WriteBookmark(const char* title_data,
|
||||
size_t title_len,
|
||||
const char* url_data,
|
||||
size_t url_len) {
|
||||
WriteHyperlink(title_data, title_len, url_data, url_len);
|
||||
}
|
||||
|
||||
void Clipboard::WriteHyperlink(const std::wstring& title,
|
||||
const std::string& url) {
|
||||
void Clipboard::WriteHyperlink(const char* title_data,
|
||||
size_t title_len,
|
||||
const char* url_data,
|
||||
size_t url_len) {
|
||||
std::string title_str(title_data, title_len);
|
||||
NSString *title = base::SysUTF8ToNSString(title_str);
|
||||
std::string url_str(url_data, url_len);
|
||||
NSString *url = base::SysUTF8ToNSString(url_str);
|
||||
|
||||
// TODO(playmobil): In the Windows version of this function, an HTML
|
||||
// representation of the bookmark is also added to the clipboard, to support
|
||||
// drag and drop of web shortcuts. I don't think we need to do this on the
|
||||
// Mac, but we should double check later on.
|
||||
NSURL* nsurl = [NSURL URLWithString:
|
||||
[NSString stringWithUTF8String:url.c_str()]];
|
||||
NSString* nstitle = base::SysWideToNSString(title);
|
||||
NSURL* nsurl = [NSURL URLWithString:url];
|
||||
|
||||
NSPasteboard* pb = GetPasteboard();
|
||||
// passing UTIs into the pasteboard methods is valid >= 10.5
|
||||
@ -73,19 +93,27 @@ void Clipboard::WriteHyperlink(const std::wstring& title,
|
||||
nil]
|
||||
owner:nil];
|
||||
[nsurl writeToPasteboard:pb];
|
||||
[pb setString:nstitle forType:kUTTypeURLName];
|
||||
[pb setString:title forType:kUTTypeURLName];
|
||||
}
|
||||
|
||||
void Clipboard::WriteFile(const std::wstring& file) {
|
||||
std::vector<std::wstring> files;
|
||||
files.push_back(file);
|
||||
WriteFiles(files);
|
||||
}
|
||||
void Clipboard::WriteFiles(const char* file_data, size_t file_len) {
|
||||
NSMutableArray* fileList = [NSMutableArray arrayWithCapacity:1];
|
||||
|
||||
void Clipboard::WriteFiles(const std::vector<std::wstring>& files) {
|
||||
NSMutableArray* fileList = [NSMutableArray arrayWithCapacity:files.size()];
|
||||
for (size_t i = 0; i < files.size(); ++i) {
|
||||
[fileList addObject:base::SysWideToNSString(files[i])];
|
||||
// Offset of current filename from start of file_data array.
|
||||
size_t current_filename_offset = 0;
|
||||
|
||||
// file_data is double null terminated (see table at top of clipboard.h).
|
||||
// So this loop can ignore the second null terminator, thus file_len - 1.
|
||||
// TODO(playmobil): If we need a loop like this on other platforms then split
|
||||
// this out into a common function that outputs a std::vector<const char*>.
|
||||
for (size_t i = 0; i < file_len - 1; ++i) {
|
||||
if (file_data[i] == '\0') {
|
||||
const char* filename = &file_data[current_filename_offset];
|
||||
[fileList addObject:[NSString stringWithUTF8String:filename]];
|
||||
|
||||
current_filename_offset = i + 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
NSPasteboard* pb = GetPasteboard();
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "base/basictypes.h"
|
||||
#include "base/clipboard.h"
|
||||
#include "base/platform_test.h"
|
||||
#include "base/scoped_clipboard_writer.h"
|
||||
#include "base/string_util.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
@ -15,13 +16,20 @@ typedef PlatformTest ClipboardTest;
|
||||
TEST_F(ClipboardTest, ClearTest) {
|
||||
Clipboard clipboard;
|
||||
|
||||
clipboard.Clear();
|
||||
clipboard.WriteText(L"erase me");
|
||||
clipboard.Clear();
|
||||
EXPECT_EQ(false, clipboard.IsFormatAvailable(
|
||||
{
|
||||
ScopedClipboardWriter scw(&clipboard);
|
||||
scw.WriteText(std::wstring(L"clear me"));
|
||||
}
|
||||
|
||||
{
|
||||
ScopedClipboardWriter scw(&clipboard);
|
||||
scw.WriteHTML(std::wstring(L"<b>broom</b>"), "");
|
||||
}
|
||||
|
||||
EXPECT_FALSE(clipboard.IsFormatAvailable(
|
||||
Clipboard::GetPlainTextWFormatType()));
|
||||
EXPECT_FALSE(clipboard.IsFormatAvailable(
|
||||
Clipboard::GetPlainTextFormatType()));
|
||||
EXPECT_EQ(false, clipboard.IsFormatAvailable(
|
||||
Clipboard::GetHtmlFormatType()));
|
||||
}
|
||||
|
||||
TEST_F(ClipboardTest, TextTest) {
|
||||
@ -30,11 +38,14 @@ TEST_F(ClipboardTest, TextTest) {
|
||||
std::wstring text(L"This is a wstring!#$"), text_result;
|
||||
std::string ascii_text;
|
||||
|
||||
clipboard.Clear();
|
||||
clipboard.WriteText(text);
|
||||
EXPECT_EQ(true, clipboard.IsFormatAvailable(
|
||||
{
|
||||
ScopedClipboardWriter scw(&clipboard);
|
||||
scw.WriteText(text);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(clipboard.IsFormatAvailable(
|
||||
Clipboard::GetPlainTextWFormatType()));
|
||||
EXPECT_EQ(true, clipboard.IsFormatAvailable(
|
||||
EXPECT_TRUE(clipboard.IsFormatAvailable(
|
||||
Clipboard::GetPlainTextFormatType()));
|
||||
clipboard.ReadText(&text_result);
|
||||
EXPECT_EQ(text, text_result);
|
||||
@ -42,29 +53,17 @@ TEST_F(ClipboardTest, TextTest) {
|
||||
EXPECT_EQ(WideToUTF8(text), ascii_text);
|
||||
}
|
||||
|
||||
TEST_F(ClipboardTest, OverwriteTest) {
|
||||
Clipboard clipboard;
|
||||
|
||||
std::wstring text1(L"first string"), text2(L"second string"), text_result;
|
||||
|
||||
clipboard.Clear();
|
||||
clipboard.WriteText(text1);
|
||||
clipboard.WriteText(text2);
|
||||
|
||||
EXPECT_TRUE(clipboard.IsFormatAvailable(
|
||||
Clipboard::GetPlainTextWFormatType()));
|
||||
clipboard.ReadText(&text_result);
|
||||
EXPECT_EQ(text2, text_result);
|
||||
}
|
||||
|
||||
TEST_F(ClipboardTest, HTMLTest) {
|
||||
Clipboard clipboard;
|
||||
|
||||
std::wstring markup(L"<strong>Hi!</string>"), markup_result;
|
||||
std::wstring markup(L"<string>Hi!</string>"), markup_result;
|
||||
std::string url("http://www.example.com/"), url_result;
|
||||
|
||||
clipboard.Clear();
|
||||
clipboard.WriteHTML(markup, url);
|
||||
{
|
||||
ScopedClipboardWriter scw(&clipboard);
|
||||
scw.WriteHTML(markup, url);
|
||||
}
|
||||
|
||||
EXPECT_EQ(true, clipboard.IsFormatAvailable(
|
||||
Clipboard::GetHtmlFormatType()));
|
||||
clipboard.ReadHTML(&markup_result, &url_result);
|
||||
@ -82,8 +81,11 @@ TEST_F(ClipboardTest, TrickyHTMLTest) {
|
||||
std::wstring markup(L"<em>Bye!<!--EndFragment --></em>"), markup_result;
|
||||
std::string url, url_result;
|
||||
|
||||
clipboard.Clear();
|
||||
clipboard.WriteHTML(markup, url);
|
||||
{
|
||||
ScopedClipboardWriter scw(&clipboard);
|
||||
scw.WriteHTML(markup, url);
|
||||
}
|
||||
|
||||
EXPECT_EQ(true, clipboard.IsFormatAvailable(
|
||||
Clipboard::GetHtmlFormatType()));
|
||||
clipboard.ReadHTML(&markup_result, &url_result);
|
||||
@ -103,8 +105,11 @@ TEST_F(ClipboardTest, BookmarkTest) {
|
||||
std::wstring title(L"The Example Company"), title_result;
|
||||
std::string url("http://www.example.com/"), url_result;
|
||||
|
||||
clipboard.Clear();
|
||||
clipboard.WriteBookmark(title, url);
|
||||
{
|
||||
ScopedClipboardWriter scw(&clipboard);
|
||||
scw.WriteBookmark(title, url);
|
||||
}
|
||||
|
||||
EXPECT_EQ(true,
|
||||
clipboard.IsFormatAvailable(Clipboard::GetUrlWFormatType()));
|
||||
clipboard.ReadBookmark(&title_result, &url_result);
|
||||
@ -121,9 +126,12 @@ TEST_F(ClipboardTest, MultiFormatTest) {
|
||||
std::string url("http://www.example.com/"), url_result;
|
||||
std::string ascii_text;
|
||||
|
||||
clipboard.Clear();
|
||||
clipboard.WriteHTML(markup, url);
|
||||
clipboard.WriteText(text);
|
||||
{
|
||||
ScopedClipboardWriter scw(&clipboard);
|
||||
scw.WriteHTML(markup, url);
|
||||
scw.WriteText(text);
|
||||
}
|
||||
|
||||
EXPECT_EQ(true,
|
||||
clipboard.IsFormatAvailable(Clipboard::GetHtmlFormatType()));
|
||||
EXPECT_EQ(true, clipboard.IsFormatAvailable(
|
||||
@ -149,7 +157,6 @@ TEST_F(ClipboardTest, MultiFormatTest) {
|
||||
// don't try to use a non-existent file you've retrieved from the clipboard.
|
||||
TEST_F(ClipboardTest, FileTest) {
|
||||
Clipboard clipboard;
|
||||
clipboard.Clear();
|
||||
#if defined(OS_WIN)
|
||||
std::wstring file = L"C:\\Downloads\\My Downloads\\A Special File.txt";
|
||||
#else
|
||||
@ -157,7 +164,12 @@ TEST_F(ClipboardTest, FileTest) {
|
||||
// clipboard.
|
||||
std::wstring file = L"/usr/bin/make";
|
||||
#endif
|
||||
clipboard.WriteFile(file);
|
||||
|
||||
{
|
||||
ScopedClipboardWriter scw(&clipboard);
|
||||
scw.WriteFile(file);
|
||||
}
|
||||
|
||||
std::wstring out_file;
|
||||
clipboard.ReadFile(&out_file);
|
||||
EXPECT_EQ(file, out_file);
|
||||
@ -165,8 +177,7 @@ TEST_F(ClipboardTest, FileTest) {
|
||||
|
||||
TEST_F(ClipboardTest, MultipleFilesTest) {
|
||||
Clipboard clipboard;
|
||||
clipboard.Clear();
|
||||
|
||||
|
||||
#if defined(OS_WIN)
|
||||
std::wstring file1 = L"C:\\Downloads\\My Downloads\\File 1.exe";
|
||||
std::wstring file2 = L"C:\\Downloads\\My Downloads\\File 2.pdf";
|
||||
@ -182,7 +193,11 @@ TEST_F(ClipboardTest, MultipleFilesTest) {
|
||||
files.push_back(file1);
|
||||
files.push_back(file2);
|
||||
files.push_back(file3);
|
||||
clipboard.WriteFiles(files);
|
||||
|
||||
{
|
||||
ScopedClipboardWriter scw(&clipboard);
|
||||
scw.WriteFiles(files);
|
||||
}
|
||||
|
||||
std::vector<std::wstring> out_files;
|
||||
clipboard.ReadFiles(&out_files);
|
||||
@ -196,14 +211,17 @@ TEST_F(ClipboardTest, MultipleFilesTest) {
|
||||
#if defined(OS_WIN) // Windows only tests.
|
||||
TEST_F(ClipboardTest, HyperlinkTest) {
|
||||
Clipboard clipboard;
|
||||
|
||||
|
||||
std::wstring title(L"The Example Company"), title_result;
|
||||
std::string url("http://www.example.com/"), url_result;
|
||||
std::wstring html(L"<a href=\"http://www.example.com/\">"
|
||||
L"The Example Company</a>"), html_result;
|
||||
|
||||
clipboard.Clear();
|
||||
clipboard.WriteHyperlink(title, url);
|
||||
|
||||
{
|
||||
ScopedClipboardWriter scw(&clipboard);
|
||||
scw.WriteHyperlink(title, url);
|
||||
}
|
||||
|
||||
EXPECT_EQ(true,
|
||||
clipboard.IsFormatAvailable(Clipboard::GetUrlWFormatType()));
|
||||
EXPECT_EQ(true,
|
||||
@ -219,8 +237,11 @@ TEST_F(ClipboardTest, HyperlinkTest) {
|
||||
TEST_F(ClipboardTest, WebSmartPasteTest) {
|
||||
Clipboard clipboard;
|
||||
|
||||
clipboard.Clear();
|
||||
clipboard.WriteWebSmartPaste();
|
||||
{
|
||||
ScopedClipboardWriter scw(&clipboard);
|
||||
scw.WriteWebSmartPaste();
|
||||
}
|
||||
|
||||
EXPECT_EQ(true, clipboard.IsFormatAvailable(
|
||||
Clipboard::GetWebKitSmartPasteFormatType()));
|
||||
}
|
||||
@ -234,8 +255,11 @@ TEST_F(ClipboardTest, BitmapTest) {
|
||||
|
||||
Clipboard clipboard;
|
||||
|
||||
clipboard.Clear();
|
||||
clipboard.WriteBitmap(fake_bitmap, gfx::Size(3, 4));
|
||||
{
|
||||
ScopedClipboardWriter scw(&clipboard);
|
||||
scw.WriteBitmapFromPixels(fake_bitmap, gfx::Size(3, 4));
|
||||
}
|
||||
|
||||
EXPECT_EQ(true, clipboard.IsFormatAvailable(
|
||||
Clipboard::GetBitmapFormatType()));
|
||||
}
|
||||
|
@ -149,82 +149,94 @@ Clipboard::~Clipboard() {
|
||||
clipboard_owner_ = NULL;
|
||||
}
|
||||
|
||||
void Clipboard::Clear() {
|
||||
// Acquire the clipboard.
|
||||
void Clipboard::WriteObjects(const ObjectMap& objects) {
|
||||
WriteObjects(objects, NULL);
|
||||
}
|
||||
|
||||
void Clipboard::WriteObjects(const ObjectMap& objects, ProcessHandle process) {
|
||||
ClipboardLock lock;
|
||||
if (!lock.Acquire(clipboard_owner_))
|
||||
return;
|
||||
|
||||
::EmptyClipboard();
|
||||
|
||||
for (ObjectMap::const_iterator iter = objects.begin();
|
||||
iter != objects.end(); ++iter) {
|
||||
if (iter->first == CBF_SMBITMAP)
|
||||
WriteBitmapFromSharedMemory(&(iter->second[0].front()),
|
||||
&(iter->second[1].front()),
|
||||
process);
|
||||
else
|
||||
DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
|
||||
}
|
||||
}
|
||||
|
||||
void Clipboard::WriteText(const std::wstring& text) {
|
||||
ClipboardLock lock;
|
||||
if (!lock.Acquire(clipboard_owner_))
|
||||
return;
|
||||
|
||||
void Clipboard::WriteText(const char* text_data, size_t text_len) {
|
||||
std::wstring text;
|
||||
UTF8ToWide(text_data, text_len, &text);
|
||||
HGLOBAL glob = CreateGlobalData(text);
|
||||
if (glob && !::SetClipboardData(CF_UNICODETEXT, glob))
|
||||
::GlobalFree(glob);
|
||||
|
||||
WriteToClipboard(CF_UNICODETEXT, glob);
|
||||
}
|
||||
|
||||
void Clipboard::WriteHTML(const std::wstring& markup,
|
||||
const std::string& url) {
|
||||
// Acquire the clipboard.
|
||||
ClipboardLock lock;
|
||||
if (!lock.Acquire(clipboard_owner_))
|
||||
return;
|
||||
void Clipboard::WriteHTML(const char* markup_data,
|
||||
size_t markup_len,
|
||||
const char* url_data,
|
||||
size_t url_len) {
|
||||
std::string html_fragment,
|
||||
markup(markup_data, markup_len),
|
||||
url;
|
||||
|
||||
if (url_len > 0)
|
||||
url.assign(url_data, url_len);
|
||||
|
||||
std::string html_fragment;
|
||||
MarkupToHTMLClipboardFormat(markup, url, &html_fragment);
|
||||
HGLOBAL glob = CreateGlobalData(html_fragment);
|
||||
if (glob && !::SetClipboardData(GetHtmlFormatType(), glob)) {
|
||||
::GlobalFree(glob);
|
||||
}
|
||||
|
||||
WriteToClipboard(GetHtmlFormatType(), glob);
|
||||
}
|
||||
|
||||
void Clipboard::WriteBookmark(const std::wstring& title,
|
||||
const std::string& url) {
|
||||
// Acquire the clipboard.
|
||||
ClipboardLock lock;
|
||||
if (!lock.Acquire(clipboard_owner_))
|
||||
return;
|
||||
|
||||
std::wstring bookmark(title);
|
||||
void Clipboard::WriteBookmark(const char* title_data,
|
||||
size_t title_len,
|
||||
const char* url_data,
|
||||
size_t url_len) {
|
||||
std::string bookmark(title_data, title_len);
|
||||
bookmark.append(1, L'\n');
|
||||
bookmark.append(UTF8ToWide(url));
|
||||
HGLOBAL glob = CreateGlobalData(bookmark);
|
||||
if (glob && !::SetClipboardData(GetUrlWFormatType(), glob)) {
|
||||
::GlobalFree(glob);
|
||||
}
|
||||
bookmark.append(url_data, url_len);
|
||||
|
||||
std::wstring wide_bookmark = UTF8ToWide(bookmark);
|
||||
HGLOBAL glob = CreateGlobalData(wide_bookmark);
|
||||
|
||||
WriteToClipboard(GetUrlWFormatType(), glob);
|
||||
}
|
||||
|
||||
void Clipboard::WriteHyperlink(const std::wstring& title,
|
||||
const std::string& url) {
|
||||
// Write as a bookmark.
|
||||
WriteBookmark(title, url);
|
||||
void Clipboard::WriteHyperlink(const char* title_data,
|
||||
size_t title_len,
|
||||
const char* url_data,
|
||||
size_t url_len) {
|
||||
// Store as a bookmark.
|
||||
WriteBookmark(title_data, title_len, url_data, url_len);
|
||||
|
||||
// Build the HTML link.
|
||||
std::wstring link(L"<a href=\"");
|
||||
link.append(UTF8ToWide(url));
|
||||
link.append(L"\">");
|
||||
std::string title(title_data, title_len),
|
||||
url(url_data, url_len),
|
||||
link("<a href=\"");
|
||||
|
||||
// Construct the hyperlink.
|
||||
link.append(url);
|
||||
link.append("\">");
|
||||
link.append(title);
|
||||
link.append(L"</a>");
|
||||
link.append("</a>");
|
||||
|
||||
// Write as an HTML link.
|
||||
WriteHTML(link, std::string());
|
||||
// Store hyperlink as html.
|
||||
WriteHTML(link.c_str(), link.size(), NULL, 0);
|
||||
}
|
||||
|
||||
void Clipboard::WriteWebSmartPaste() {
|
||||
// Acquire the clipboard.
|
||||
ClipboardLock lock;
|
||||
if (!lock.Acquire(clipboard_owner_))
|
||||
return;
|
||||
|
||||
SetClipboardData(GetWebKitSmartPasteFormatType(), NULL);
|
||||
::SetClipboardData(GetWebKitSmartPasteFormatType(), NULL);
|
||||
}
|
||||
|
||||
void Clipboard::WriteBitmap(const void* pixels, const gfx::Size& size) {
|
||||
void Clipboard::WriteBitmap(const char* pixel_data, const char* size_data) {
|
||||
const gfx::Size* size = reinterpret_cast<const gfx::Size*>(size_data);
|
||||
HDC dc = ::GetDC(NULL);
|
||||
|
||||
// This doesn't actually cost us a memcpy when the bitmap comes from the
|
||||
@ -234,8 +246,8 @@ void Clipboard::WriteBitmap(const void* pixels, const gfx::Size& size) {
|
||||
// TODO(darin): share data in gfx/bitmap_header.cc somehow
|
||||
BITMAPINFO bm_info = {0};
|
||||
bm_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bm_info.bmiHeader.biWidth = size.width();
|
||||
bm_info.bmiHeader.biHeight = -size.height(); // sets vertical orientation
|
||||
bm_info.bmiHeader.biWidth = size->width();
|
||||
bm_info.bmiHeader.biHeight = -size->height(); // sets vertical orientation
|
||||
bm_info.bmiHeader.biPlanes = 1;
|
||||
bm_info.bmiHeader.biBitCount = 32;
|
||||
bm_info.bmiHeader.biCompression = BI_RGB;
|
||||
@ -249,23 +261,30 @@ void Clipboard::WriteBitmap(const void* pixels, const gfx::Size& size) {
|
||||
|
||||
if (bits && source_hbitmap) {
|
||||
// Copy the bitmap out of shared memory and into GDI
|
||||
memcpy(bits, pixels, 4 * size.width() * size.height());
|
||||
memcpy(bits, pixel_data, 4 * size->width() * size->height());
|
||||
|
||||
// Now we have an HBITMAP, we can write it to the clipboard
|
||||
WriteBitmapFromHandle(source_hbitmap, size);
|
||||
WriteBitmapFromHandle(source_hbitmap, *size);
|
||||
}
|
||||
|
||||
::DeleteObject(source_hbitmap);
|
||||
::ReleaseDC(NULL, dc);
|
||||
}
|
||||
|
||||
void Clipboard::WriteBitmapFromSharedMemory(const SharedMemory& bitmap,
|
||||
const gfx::Size& size) {
|
||||
void Clipboard::WriteBitmapFromSharedMemory(const char* bitmap_data,
|
||||
const char* size_data,
|
||||
ProcessHandle process) {
|
||||
const SharedMemoryHandle* remote_bitmap_handle =
|
||||
reinterpret_cast<const SharedMemoryHandle*>(bitmap_data);
|
||||
const gfx::Size* size = reinterpret_cast<const gfx::Size*>(size_data);
|
||||
|
||||
SharedMemory bitmap(*remote_bitmap_handle, false, process);
|
||||
|
||||
// TODO(darin): share data in gfx/bitmap_header.cc somehow
|
||||
BITMAPINFO bm_info = {0};
|
||||
bm_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bm_info.bmiHeader.biWidth = size.width();
|
||||
bm_info.bmiHeader.biHeight = -size.height(); // Sets the vertical orientation
|
||||
bm_info.bmiHeader.biWidth = size->width();
|
||||
bm_info.bmiHeader.biHeight = -size->height(); // Sets the vertical orientation
|
||||
bm_info.bmiHeader.biPlanes = 1;
|
||||
bm_info.bmiHeader.biBitCount = 32;
|
||||
bm_info.bmiHeader.biCompression = BI_RGB;
|
||||
@ -275,11 +294,12 @@ void Clipboard::WriteBitmapFromSharedMemory(const SharedMemory& bitmap,
|
||||
// We can create an HBITMAP directly using the shared memory handle, saving
|
||||
// a memcpy.
|
||||
HBITMAP source_hbitmap =
|
||||
::CreateDIBSection(dc, &bm_info, DIB_RGB_COLORS, NULL, bitmap.handle(), 0);
|
||||
::CreateDIBSection(dc, &bm_info, DIB_RGB_COLORS, NULL,
|
||||
bitmap.handle(), 0);
|
||||
|
||||
if (source_hbitmap) {
|
||||
// Now we can write the HBITMAP to the clipboard
|
||||
WriteBitmapFromHandle(source_hbitmap, size);
|
||||
WriteBitmapFromHandle(source_hbitmap, *size);
|
||||
}
|
||||
|
||||
::DeleteObject(source_hbitmap);
|
||||
@ -288,11 +308,6 @@ void Clipboard::WriteBitmapFromSharedMemory(const SharedMemory& bitmap,
|
||||
|
||||
void Clipboard::WriteBitmapFromHandle(HBITMAP source_hbitmap,
|
||||
const gfx::Size& size) {
|
||||
// Acquire the clipboard.
|
||||
ClipboardLock lock;
|
||||
if (!lock.Acquire(clipboard_owner_))
|
||||
return;
|
||||
|
||||
// We would like to just call ::SetClipboardData on the source_hbitmap,
|
||||
// but that bitmap might not be of a sort we can write to the clipboard.
|
||||
// For this reason, we create a new bitmap, copy the bits over, and then
|
||||
@ -329,52 +344,37 @@ void Clipboard::WriteBitmapFromHandle(HBITMAP source_hbitmap,
|
||||
::DeleteDC(source_dc);
|
||||
::ReleaseDC(NULL, dc);
|
||||
|
||||
// Actually write the bitmap to the clipboard
|
||||
::SetClipboardData(CF_BITMAP, hbitmap);
|
||||
WriteToClipboard(CF_BITMAP, hbitmap);
|
||||
}
|
||||
|
||||
// Write a file or set of files to the clipboard in HDROP format. When the user
|
||||
// invokes a paste command (in a Windows explorer shell, for example), the files
|
||||
// will be copied to the paste location.
|
||||
void Clipboard::WriteFile(const std::wstring& file) {
|
||||
std::vector<std::wstring> files;
|
||||
files.push_back(file);
|
||||
WriteFiles(files);
|
||||
}
|
||||
|
||||
void Clipboard::WriteFiles(const std::vector<std::wstring>& files) {
|
||||
ClipboardLock lock;
|
||||
if (!lock.Acquire(clipboard_owner_))
|
||||
return;
|
||||
|
||||
// Calculate the amount of space we'll need store the strings: require
|
||||
// NULL terminator between strings, and double null terminator at the end.
|
||||
size_t bytes = sizeof(DROPFILES);
|
||||
for (size_t i = 0; i < files.size(); ++i)
|
||||
bytes += (files[i].length() + 1) * sizeof(wchar_t);
|
||||
bytes += sizeof(wchar_t);
|
||||
void Clipboard::WriteFiles(const char* file_data, size_t file_len) {
|
||||
std::wstring filenames(UTF8ToWide(std::string(file_data, file_len)));
|
||||
// Calculate the amount of space we'll need store the strings and
|
||||
// a DROPFILES struct.
|
||||
size_t bytes = sizeof(DROPFILES) + filenames.length() * sizeof(wchar_t);
|
||||
|
||||
HANDLE hdata = ::GlobalAlloc(GMEM_MOVEABLE, bytes);
|
||||
if (!hdata)
|
||||
return;
|
||||
|
||||
DROPFILES* drop_files = static_cast<DROPFILES*>(::GlobalLock(hdata));
|
||||
char* data = static_cast<char*>(::GlobalLock(hdata));
|
||||
DROPFILES* drop_files = reinterpret_cast<DROPFILES*>(data);
|
||||
drop_files->pFiles = sizeof(DROPFILES);
|
||||
drop_files->fWide = TRUE;
|
||||
BYTE* data = reinterpret_cast<BYTE*>(drop_files) + sizeof(DROPFILES);
|
||||
|
||||
// Copy the strings stored in 'files' with proper NULL separation.
|
||||
wchar_t* data_pos = reinterpret_cast<wchar_t*>(data);
|
||||
for (size_t i = 0; i < files.size(); ++i) {
|
||||
size_t offset = files[i].length() + 1;
|
||||
memcpy(data_pos, files[i].c_str(), offset * sizeof(wchar_t));
|
||||
data_pos += offset;
|
||||
}
|
||||
data_pos[0] = L'\0'; // Double NULL termination after the last string.
|
||||
memcpy(data + sizeof DROPFILES, filenames.c_str(),
|
||||
filenames.length() * sizeof(wchar_t));
|
||||
|
||||
::GlobalUnlock(hdata);
|
||||
if (!::SetClipboardData(CF_HDROP, hdata))
|
||||
::GlobalFree(hdata);
|
||||
WriteToClipboard(CF_HDROP, hdata);
|
||||
}
|
||||
|
||||
void Clipboard::WriteToClipboard(FormatType format, HANDLE handle) {
|
||||
if (handle && !::SetClipboardData(format, handle))
|
||||
FreeData(format, handle);
|
||||
}
|
||||
|
||||
bool Clipboard::IsFormatAvailable(unsigned int format) const {
|
||||
@ -514,7 +514,7 @@ void Clipboard::ReadFiles(std::vector<std::wstring>* files) const {
|
||||
}
|
||||
|
||||
// static
|
||||
void Clipboard::MarkupToHTMLClipboardFormat(const std::wstring& markup,
|
||||
void Clipboard::MarkupToHTMLClipboardFormat(const std::string& markup,
|
||||
const std::string& src_url,
|
||||
std::string* html_fragment) {
|
||||
DCHECK(html_fragment);
|
||||
@ -526,8 +526,6 @@ void Clipboard::MarkupToHTMLClipboardFormat(const std::wstring& markup,
|
||||
return;
|
||||
}
|
||||
|
||||
std::string markup_utf8 = WideToUTF8(markup);
|
||||
|
||||
html_fragment->assign("Version:0.9");
|
||||
|
||||
std::string start_html("\nStartHTML:");
|
||||
@ -557,7 +555,7 @@ void Clipboard::MarkupToHTMLClipboardFormat(const std::wstring& markup,
|
||||
(4*kMaxDigits);
|
||||
|
||||
start_fragment_offset = start_html_offset + start_markup.length();
|
||||
end_fragment_offset = start_fragment_offset + markup_utf8.length();
|
||||
end_fragment_offset = start_fragment_offset + markup.length();
|
||||
end_html_offset = end_fragment_offset + end_markup.length();
|
||||
|
||||
// fill in needed data
|
||||
@ -565,7 +563,7 @@ void Clipboard::MarkupToHTMLClipboardFormat(const std::wstring& markup,
|
||||
end_html.append(StringPrintf("%010u", end_html_offset));
|
||||
start_fragment.append(StringPrintf("%010u", start_fragment_offset));
|
||||
end_fragment.append(StringPrintf("%010u", end_fragment_offset));
|
||||
start_markup.append(markup_utf8);
|
||||
start_markup.append(markup);
|
||||
|
||||
// create full html_fragment string from the fragments
|
||||
html_fragment->append(start_html);
|
||||
@ -702,3 +700,10 @@ Clipboard::FormatType Clipboard::GetWebKitSmartPasteFormatType() {
|
||||
return ClipboardUtil::GetWebKitSmartPasteFormat()->cfFormat;
|
||||
}
|
||||
|
||||
// static
|
||||
void Clipboard::FreeData(FormatType format, HANDLE data) {
|
||||
if (format == CF_BITMAP)
|
||||
::DeleteObject(static_cast<HBITMAP>(data));
|
||||
else
|
||||
::GlobalFree(data);
|
||||
}
|
||||
|
130
base/scoped_clipboard_writer.cc
Normal file
130
base/scoped_clipboard_writer.cc
Normal file
@ -0,0 +1,130 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/scoped_clipboard_writer.h"
|
||||
|
||||
#include "base/clipboard.h"
|
||||
#include "base/string_util.h"
|
||||
|
||||
ScopedClipboardWriter::ScopedClipboardWriter(Clipboard* clipboard)
|
||||
: clipboard_(clipboard) {
|
||||
}
|
||||
|
||||
ScopedClipboardWriter::~ScopedClipboardWriter() {
|
||||
if (!objects_.empty() && clipboard_)
|
||||
clipboard_->WriteObjects(objects_);
|
||||
}
|
||||
|
||||
void ScopedClipboardWriter::WriteText(const std::wstring& text) {
|
||||
if (text.empty())
|
||||
return;
|
||||
|
||||
std::string utf8_text = WideToUTF8(text);
|
||||
|
||||
Clipboard::ObjectMapParams params;
|
||||
params.push_back(Clipboard::ObjectMapParam(utf8_text.begin(),
|
||||
utf8_text.end()));
|
||||
objects_[Clipboard::CBF_TEXT] = params;
|
||||
}
|
||||
|
||||
void ScopedClipboardWriter::WriteHTML(const std::wstring& markup,
|
||||
const std::string& src_url) {
|
||||
if (markup.empty())
|
||||
return;
|
||||
|
||||
std::string utf8_markup = WideToUTF8(markup);
|
||||
|
||||
Clipboard::ObjectMapParams params;
|
||||
params.push_back(
|
||||
Clipboard::ObjectMapParam(utf8_markup.begin(),
|
||||
utf8_markup.end()));
|
||||
if (!src_url.empty()) {
|
||||
params.push_back(Clipboard::ObjectMapParam(src_url.begin(),
|
||||
src_url.end()));
|
||||
}
|
||||
|
||||
objects_[Clipboard::CBF_HTML] = params;
|
||||
}
|
||||
|
||||
void ScopedClipboardWriter::WriteBookmark(const std::wstring& title,
|
||||
const std::string& url) {
|
||||
if (title.empty() || url.empty())
|
||||
return;
|
||||
|
||||
std::string utf8_markup = WideToUTF8(title);
|
||||
|
||||
Clipboard::ObjectMapParams params;
|
||||
params.push_back(Clipboard::ObjectMapParam(utf8_markup.begin(),
|
||||
utf8_markup.end()));
|
||||
params.push_back(Clipboard::ObjectMapParam(url.begin(), url.end()));
|
||||
objects_[Clipboard::CBF_BOOKMARK] = params;
|
||||
}
|
||||
|
||||
void ScopedClipboardWriter::WriteHyperlink(const std::wstring& title,
|
||||
const std::string& url) {
|
||||
if (title.empty() || url.empty())
|
||||
return;
|
||||
|
||||
std::string utf8_markup = WideToUTF8(title);
|
||||
|
||||
Clipboard::ObjectMapParams params;
|
||||
params.push_back(Clipboard::ObjectMapParam(utf8_markup.begin(),
|
||||
utf8_markup.end()));
|
||||
params.push_back(Clipboard::ObjectMapParam(url.begin(), url.end()));
|
||||
objects_[Clipboard::CBF_LINK] = params;
|
||||
}
|
||||
|
||||
void ScopedClipboardWriter::WriteFile(const std::wstring& file) {
|
||||
WriteFiles(std::vector<std::wstring>(1, file));
|
||||
}
|
||||
|
||||
// Save the filenames as a string separated by nulls and terminated with an
|
||||
// extra null.
|
||||
void ScopedClipboardWriter::WriteFiles(const std::vector<std::wstring>& files) {
|
||||
if (files.empty())
|
||||
return;
|
||||
|
||||
Clipboard::ObjectMapParam param;
|
||||
|
||||
for (std::vector<std::wstring>::const_iterator iter = files.begin();
|
||||
iter != files.end(); ++iter) {
|
||||
std::string filename = WideToUTF8(*iter);
|
||||
for (std::string::const_iterator filename_iter = filename.begin();
|
||||
filename_iter != filename.end(); ++filename_iter) {
|
||||
param.push_back(*filename_iter);
|
||||
}
|
||||
param.push_back('\0');
|
||||
}
|
||||
|
||||
param.push_back('\0');
|
||||
|
||||
Clipboard::ObjectMapParams params;
|
||||
params.push_back(param);
|
||||
objects_[Clipboard::CBF_FILES] = params;
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void ScopedClipboardWriter::WriteWebSmartPaste() {
|
||||
objects_[Clipboard::CBF_WEBKIT] = Clipboard::ObjectMapParams();
|
||||
}
|
||||
|
||||
void ScopedClipboardWriter::WriteBitmapFromPixels(const void* pixels,
|
||||
const gfx::Size& size) {
|
||||
Clipboard::ObjectMapParam param1, param2;
|
||||
const char* pixels_data = reinterpret_cast<const char*>(pixels);
|
||||
size_t pixels_len = 4 * size.width() * size.height();
|
||||
for (size_t i = 0; i < pixels_len; i++)
|
||||
param1.push_back(pixels_data[i]);
|
||||
|
||||
const char* size_data = reinterpret_cast<const char*>(&size);
|
||||
size_t size_len = sizeof(gfx::Size);
|
||||
for (size_t i = 0; i < size_len; i++)
|
||||
param2.push_back(size_data[i]);
|
||||
|
||||
Clipboard::ObjectMapParams params;
|
||||
params.push_back(param1);
|
||||
params.push_back(param2);
|
||||
objects_[Clipboard::CBF_BITMAP] = params;
|
||||
}
|
||||
#endif // defined(OS_WIN)
|
62
base/scoped_clipboard_writer.h
Normal file
62
base/scoped_clipboard_writer.h
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef SCOPED_CLIPBOARD_WRITER_H_
|
||||
#define SCOPED_CLIPBOARD_WRITER_H_
|
||||
|
||||
#include "base/clipboard.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
class SkBitmap;
|
||||
#endif
|
||||
|
||||
// This class is a wrapper for |Clipboard| that handles packing data
|
||||
// into a Clipboard::ObjectMap.
|
||||
// NB: You should probably NOT be using this class if you include
|
||||
// webkit_glue.h. Use ScopedClipboardWriterGlue instead.
|
||||
class ScopedClipboardWriter {
|
||||
public:
|
||||
// Create an instance that is a simple wrapper around clipboard.
|
||||
ScopedClipboardWriter(Clipboard* clipboard);
|
||||
|
||||
~ScopedClipboardWriter();
|
||||
|
||||
// Adds UNICODE and ASCII text to the clipboard.
|
||||
void WriteText(const std::wstring& text);
|
||||
|
||||
// Adds HTML to the clipboard. The url parameter is optional, but especially
|
||||
// useful if the HTML fragment contains relative links
|
||||
void WriteHTML(const std::wstring& markup, const std::string& src_url);
|
||||
|
||||
// Adds a bookmark to the clipboard
|
||||
void WriteBookmark(const std::wstring& title, const std::string& url);
|
||||
|
||||
// Adds both a bookmark and an HTML hyperlink to the clipboard. It is a
|
||||
// convenience wrapper around WriteBookmark and WriteHTML.
|
||||
void WriteHyperlink(const std::wstring& title, const std::string& url);
|
||||
|
||||
// Adds a file or group of files to the clipboard.
|
||||
void WriteFile(const std::wstring& file);
|
||||
void WriteFiles(const std::vector<std::wstring>& files);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Used by WebKit to determine whether WebKit wrote the clipboard last
|
||||
void WriteWebSmartPaste();
|
||||
|
||||
// Adds a bitmap to the clipboard
|
||||
// This is the slowest way to copy a bitmap to the clipboard as we must first
|
||||
// memcpy the pixels into GDI and the blit the bitmap to the clipboard.
|
||||
// Pixel format is assumed to be 32-bit BI_RGB.
|
||||
void WriteBitmapFromPixels(const void* pixels, const gfx::Size& size);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
Clipboard::ObjectMap objects_;
|
||||
Clipboard* clipboard_;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ScopedClipboardWriter);
|
||||
};
|
||||
|
||||
#endif // SCOPED_CLIPBOARD_WRITER_H_
|
@ -11,6 +11,7 @@
|
||||
#include "base/gfx/skia_utils.h"
|
||||
#include "base/iat_patch.h"
|
||||
#include "base/ref_counted.h"
|
||||
#include "base/scoped_clipboard_writer.h"
|
||||
#include "base/string_util.h"
|
||||
#include "chrome/app/chrome_dll_resource.h"
|
||||
#include "chrome/browser/autocomplete/autocomplete_popup.h"
|
||||
@ -1405,9 +1406,8 @@ void AutocompleteEditView::OnCopy() {
|
||||
if (text.empty())
|
||||
return;
|
||||
|
||||
ClipboardService* clipboard = g_browser_process->clipboard_service();
|
||||
clipboard->Clear();
|
||||
clipboard->WriteText(text);
|
||||
ScopedClipboardWriter scw(g_browser_process->clipboard_service());
|
||||
scw.WriteText(text);
|
||||
|
||||
// Check if the user is copying the whole address bar. If they are, we
|
||||
// assume they are trying to copy a URL and write this to the clipboard as a
|
||||
@ -1421,7 +1421,7 @@ void AutocompleteEditView::OnCopy() {
|
||||
// which will screw up our calculation of the desired_tld.
|
||||
GURL url;
|
||||
if (model_->GetURLForText(text, &url))
|
||||
clipboard->WriteHyperlink(text, url.spec());
|
||||
scw.WriteHyperlink(text, url.spec());
|
||||
}
|
||||
|
||||
void AutocompleteEditView::OnCut() {
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "base/base_drag_source.h"
|
||||
#include "base/file_util.h"
|
||||
#include "base/scoped_clipboard_writer.h"
|
||||
#include "base/gfx/image_operations.h"
|
||||
#include "base/string_util.h"
|
||||
#include "chrome/app/locales/locale_settings.h"
|
||||
@ -105,24 +106,20 @@ bool BaseContextMenu::IsCommandEnabled(int id) const {
|
||||
}
|
||||
|
||||
void BaseContextMenu::ExecuteCommand(int id) {
|
||||
ClipboardService* clipboard = g_browser_process->clipboard_service();
|
||||
DCHECK(clipboard);
|
||||
ScopedClipboardWriter scw(g_browser_process->clipboard_service());
|
||||
switch (id) {
|
||||
case SHOW_IN_FOLDER:
|
||||
download_->manager()->ShowDownloadInShell(download_);
|
||||
break;
|
||||
case COPY_LINK:
|
||||
clipboard->Clear();
|
||||
clipboard->WriteText(download_->url());
|
||||
scw.WriteText(download_->url());
|
||||
break;
|
||||
case COPY_PATH:
|
||||
clipboard->Clear();
|
||||
clipboard->WriteText(download_->full_path());
|
||||
scw.WriteText(download_->full_path());
|
||||
break;
|
||||
case COPY_FILE:
|
||||
// TODO(paulg): Move to OSExchangeData when implementing drag and drop?
|
||||
clipboard->Clear();
|
||||
clipboard->WriteFile(download_->full_path());
|
||||
scw.WriteFile(download_->full_path());
|
||||
break;
|
||||
case OPEN_WHEN_COMPLETE:
|
||||
OpenDownload(download_);
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/scoped_clipboard_writer.h"
|
||||
#include "base/string_util.h"
|
||||
#include "chrome/app/chrome_dll_resource.h"
|
||||
#include "chrome/common/chrome_paths.h"
|
||||
@ -65,8 +66,8 @@ void RenderViewContextMenuController::WriteTextToClipboard(
|
||||
if (!clipboard)
|
||||
return;
|
||||
|
||||
clipboard->Clear();
|
||||
clipboard->WriteText(text);
|
||||
ScopedClipboardWriter scw(clipboard);
|
||||
scw.WriteText(text);
|
||||
}
|
||||
|
||||
void RenderViewContextMenuController::WriteURLToClipboard(const GURL& url) {
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "chrome/browser/resource_message_filter.h"
|
||||
|
||||
#include "base/clipboard.h"
|
||||
#include "base/histogram.h"
|
||||
#include "base/thread.h"
|
||||
#include "chrome/browser/chrome_plugin_browsing_context.h"
|
||||
@ -125,22 +126,10 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) {
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_DnsPrefetch, OnDnsPrefetch)
|
||||
IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_PaintRect,
|
||||
render_widget_helper_->DidReceivePaintMsg(message))
|
||||
IPC_MESSAGE_FORWARD(ViewHostMsg_ClipboardClear,
|
||||
static_cast<Clipboard*>(GetClipboardService()),
|
||||
Clipboard::Clear)
|
||||
IPC_MESSAGE_FORWARD(ViewHostMsg_ClipboardWriteText,
|
||||
static_cast<Clipboard*>(GetClipboardService()),
|
||||
Clipboard::WriteText)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteHTML,
|
||||
OnClipboardWriteHTML)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteBookmark,
|
||||
OnClipboardWriteBookmark)
|
||||
// We need to do more work to marshall around bitmaps
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteBitmap,
|
||||
OnClipboardWriteBitmap)
|
||||
IPC_MESSAGE_FORWARD(ViewHostMsg_ClipboardWriteWebSmartPaste,
|
||||
static_cast<Clipboard*>(GetClipboardService()),
|
||||
Clipboard::WriteWebSmartPaste)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteObjectsAsync,
|
||||
OnClipboardWriteObjects)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteObjectsSync,
|
||||
OnClipboardWriteObjects)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardIsFormatAvailable,
|
||||
OnClipboardIsFormatAvailable)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardReadText, OnClipboardReadText)
|
||||
@ -431,26 +420,12 @@ void ResourceMessageFilter::OnDownloadUrl(const IPC::Message& message,
|
||||
request_context_);
|
||||
}
|
||||
|
||||
void ResourceMessageFilter::OnClipboardWriteHTML(const std::wstring& markup,
|
||||
const GURL& src_url) {
|
||||
GetClipboardService()->WriteHTML(markup, src_url.spec());
|
||||
}
|
||||
|
||||
void ResourceMessageFilter::OnClipboardWriteBookmark(const std::wstring& title,
|
||||
const GURL& url) {
|
||||
GetClipboardService()->WriteBookmark(title, url.spec());
|
||||
}
|
||||
|
||||
void ResourceMessageFilter::OnClipboardWriteBitmap(
|
||||
SharedMemoryHandle bitmap_buf, gfx::Size size) {
|
||||
// hbitmap here is only valid in the context of the renderer. We need to
|
||||
// import it into our process using SharedMemory in order to get a handle
|
||||
// that is valid.
|
||||
//
|
||||
// We need to ask for write permission to the shared memory in order to
|
||||
// call WriteBitmapFromSharedMemory
|
||||
SharedMemory shared_mem(bitmap_buf, false, render_handle_);
|
||||
GetClipboardService()->WriteBitmapFromSharedMemory(shared_mem, size);
|
||||
void ResourceMessageFilter::OnClipboardWriteObjects(
|
||||
const Clipboard::ObjectMap& objects) {
|
||||
// We pass the render_handle_ to assist the clipboard with using shared
|
||||
// memory objects. render_handle_ is a handle to the process that would
|
||||
// own any shared memory that might be in the object list.
|
||||
GetClipboardService()->WriteObjects(objects, render_handle_);
|
||||
}
|
||||
|
||||
void ResourceMessageFilter::OnClipboardIsFormatAvailable(unsigned int format,
|
||||
|
@ -5,6 +5,7 @@
|
||||
#ifndef CHROME_BROWSER_RENDERER_RESOURCE_MSG_FILTER_H__
|
||||
#define CHROME_BROWSER_RENDERER_RESOURCE_MSG_FILTER_H__
|
||||
|
||||
#include "base/clipboard.h"
|
||||
#include "base/gfx/rect.h"
|
||||
#include "base/gfx/native_widget_types.h"
|
||||
#include "base/ref_counted.h"
|
||||
@ -121,9 +122,7 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
|
||||
void OnDnsPrefetch(const std::vector<std::string>& hostnames);
|
||||
void OnReceiveContextMenuMsg(const IPC::Message& msg);
|
||||
// Clipboard messages
|
||||
void OnClipboardWriteHTML(const std::wstring& markup, const GURL& src_url);
|
||||
void OnClipboardWriteBookmark(const std::wstring& title, const GURL& url);
|
||||
void OnClipboardWriteBitmap(SharedMemoryHandle bitmap, gfx::Size size);
|
||||
void OnClipboardWriteObjects(const Clipboard::ObjectMap& objects);
|
||||
void OnClipboardIsFormatAvailable(unsigned int format, bool* result);
|
||||
void OnClipboardReadText(std::wstring* result);
|
||||
void OnClipboardReadAsciiText(std::string* result);
|
||||
|
@ -1,20 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Many of these functions are based on those found in
|
||||
// webkit/port/platform/PasteboardWin.cpp
|
||||
|
||||
#include "chrome/common/clipboard_service.h"
|
||||
|
||||
#include "SkBitmap.h"
|
||||
|
||||
ClipboardService::ClipboardService() {
|
||||
}
|
||||
|
||||
void ClipboardService::WriteBitmap(const SkBitmap& bitmap) {
|
||||
SkAutoLockPixels bitmap_lock(bitmap);
|
||||
Clipboard::WriteBitmap(bitmap.getPixels(),
|
||||
gfx::Size(bitmap.width(), bitmap.height()));
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef CHROME_COMMON_CLIPBOARD_SERIVCE_H__
|
||||
#define CHROME_COMMON_CLIPBOARD_SERIVCE_H__
|
||||
#ifndef CHROME_COMMON_CLIPBOARD_SERVICE_H__
|
||||
#define CHROME_COMMON_CLIPBOARD_SERVICE_H__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -14,17 +14,11 @@ class SkBitmap;
|
||||
|
||||
class ClipboardService : public Clipboard {
|
||||
public:
|
||||
ClipboardService();
|
||||
|
||||
// Adds a bitmap to the clipboard
|
||||
// This is the slowest way to copy a bitmap to the clipboard as we must fist
|
||||
// memcpy the bits into GDI and the blit the bitmap to the clipboard.
|
||||
void WriteBitmap(const SkBitmap& bitmap);
|
||||
ClipboardService() {}
|
||||
|
||||
private:
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(ClipboardService);
|
||||
};
|
||||
|
||||
#endif // CHROME_COMMON_CLIPBOARD_SERIVCE_H__
|
||||
|
||||
#endif // CHROME_COMMON_CLIPBOARD_SERVICE_H__
|
||||
|
@ -389,10 +389,6 @@
|
||||
RelativePath=".\classfactory.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\clipboard_service.cc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\clipboard_service.h"
|
||||
>
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/clipboard.h"
|
||||
#include "base/gfx/rect.h"
|
||||
#include "base/shared_memory.h"
|
||||
#include "chrome/common/ipc_message_macros.h"
|
||||
@ -783,21 +784,15 @@ IPC_BEGIN_MESSAGES(ViewHost, 2)
|
||||
std::wstring /* plugin_path */)
|
||||
|
||||
// Clipboard IPC messages
|
||||
IPC_MESSAGE_CONTROL0(ViewHostMsg_ClipboardClear)
|
||||
IPC_MESSAGE_CONTROL1(ViewHostMsg_ClipboardWriteText,
|
||||
std::wstring /* text */)
|
||||
IPC_MESSAGE_CONTROL2(ViewHostMsg_ClipboardWriteHTML,
|
||||
std::wstring /* html */,
|
||||
GURL /* url */)
|
||||
IPC_MESSAGE_CONTROL2(ViewHostMsg_ClipboardWriteBookmark,
|
||||
std::wstring /* title */,
|
||||
GURL /* url */)
|
||||
// This message is synchronized so that the renderer known when it is safe to
|
||||
|
||||
// This message is used when the object list does not contain a bitmap.
|
||||
IPC_MESSAGE_CONTROL1(ViewHostMsg_ClipboardWriteObjectsAsync,
|
||||
Clipboard::ObjectMap /* objects */)
|
||||
// This message is used when the object list contains a bitmap.
|
||||
// It is synchronized so that the renderer knows when it is safe to
|
||||
// free the shared memory used to transfer the bitmap.
|
||||
IPC_SYNC_MESSAGE_CONTROL2_0(ViewHostMsg_ClipboardWriteBitmap,
|
||||
SharedMemoryHandle /* bitmap */,
|
||||
gfx::Size /* size */)
|
||||
IPC_MESSAGE_CONTROL0(ViewHostMsg_ClipboardWriteWebSmartPaste)
|
||||
IPC_SYNC_MESSAGE_CONTROL1_0(ViewHostMsg_ClipboardWriteObjectsSync,
|
||||
Clipboard::ObjectMap /* objects */)
|
||||
IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_ClipboardIsFormatAvailable,
|
||||
int /* format */,
|
||||
bool /* result */)
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include <windows.h>
|
||||
#include <wininet.h>
|
||||
|
||||
#include "base/clipboard.h"
|
||||
#include "base/scoped_clipboard_writer.h"
|
||||
#include "chrome/renderer/net/render_dns_master.h"
|
||||
#include "chrome/common/resource_bundle.h"
|
||||
#include "chrome/plugin/npobject_util.h"
|
||||
@ -14,9 +16,12 @@
|
||||
#include "chrome/renderer/visitedlink_slave.h"
|
||||
#include "googleurl/src/url_util.h"
|
||||
#include "net/base/mime_util.h"
|
||||
#include "webkit/glue/scoped_clipboard_writer_glue.h"
|
||||
#include "webkit/glue/webframe.h"
|
||||
#include "webkit/glue/webkit_glue.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "SkBitmap.h"
|
||||
|
||||
#include <strsafe.h> // note: per msdn docs, this must *follow* other includes
|
||||
@ -66,6 +71,66 @@ class ResizableStackArray {
|
||||
size_t cur_capacity_;
|
||||
};
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// This definition of WriteBitmap uses shared memory to communicate across
|
||||
// processes.
|
||||
void ScopedClipboardWriterGlue::WriteBitmap(const SkBitmap& bitmap) {
|
||||
// do not try to write a bitmap more than once
|
||||
if (shared_buf_)
|
||||
return;
|
||||
|
||||
size_t buf_size = bitmap.getSize();
|
||||
gfx::Size size(bitmap.width(), bitmap.height());
|
||||
|
||||
// Allocate a shared memory buffer to hold the bitmap bits
|
||||
shared_buf_ = RenderProcess::AllocSharedMemory(buf_size);
|
||||
if (!shared_buf_ || !shared_buf_->Map(buf_size)) {
|
||||
NOTREACHED();
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy the bits into shared memory
|
||||
SkAutoLockPixels bitmap_lock(bitmap);
|
||||
memcpy(shared_buf_->memory(), bitmap.getPixels(), buf_size);
|
||||
shared_buf_->Unmap();
|
||||
|
||||
Clipboard::ObjectMapParam param1, param2;
|
||||
SharedMemoryHandle smh = shared_buf_->handle();
|
||||
|
||||
const char* shared_handle = reinterpret_cast<const char*>(&smh);
|
||||
for (size_t i = 0; i < sizeof SharedMemoryHandle; i++)
|
||||
param1.push_back(shared_handle[i]);
|
||||
|
||||
const char* size_data = reinterpret_cast<const char*>(&size);
|
||||
for (size_t i = 0; i < sizeof gfx::Size; i++)
|
||||
param2.push_back(size_data[i]);
|
||||
|
||||
Clipboard::ObjectMapParams params;
|
||||
params.push_back(param1);
|
||||
params.push_back(param2);
|
||||
objects_[Clipboard::CBF_SMBITMAP] = params;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Define a destructor that makes IPCs to flush the contents to the
|
||||
// system clipboard.
|
||||
ScopedClipboardWriterGlue::~ScopedClipboardWriterGlue() {
|
||||
if (objects_.empty())
|
||||
return;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
if (shared_buf_) {
|
||||
RenderThread::current()->Send(
|
||||
new ViewHostMsg_ClipboardWriteObjectsSync(objects_));
|
||||
RenderProcess::FreeSharedMemory(shared_buf_);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
RenderThread::current()->Send(
|
||||
new ViewHostMsg_ClipboardWriteObjectsAsync(objects_));
|
||||
}
|
||||
|
||||
namespace webkit_glue {
|
||||
|
||||
void PrefetchDns(const std::string& hostname) {
|
||||
@ -141,58 +206,8 @@ HCURSOR webkit_glue::LoadCursor(int cursor_id) {
|
||||
|
||||
// Clipboard glue
|
||||
|
||||
void webkit_glue::ClipboardClear() {
|
||||
RenderThread::current()->Send(new ViewHostMsg_ClipboardClear());
|
||||
}
|
||||
|
||||
void webkit_glue::ClipboardWriteText(const std::wstring& text) {
|
||||
RenderThread::current()->Send(new ViewHostMsg_ClipboardWriteText(text));
|
||||
}
|
||||
|
||||
void webkit_glue::ClipboardWriteHTML(const std::wstring& html,
|
||||
const GURL& url) {
|
||||
RenderThread::current()->Send(new ViewHostMsg_ClipboardWriteHTML(html, url));
|
||||
}
|
||||
|
||||
void webkit_glue::ClipboardWriteBookmark(const std::wstring& title,
|
||||
const GURL& url) {
|
||||
RenderThread::current()->Send(
|
||||
new ViewHostMsg_ClipboardWriteBookmark(title, url));
|
||||
}
|
||||
|
||||
// Here we need to do some work to marshal the bitmap through shared memory
|
||||
void webkit_glue::ClipboardWriteBitmap(const SkBitmap& bitmap) {
|
||||
size_t buf_size = bitmap.getSize();
|
||||
gfx::Size size(bitmap.width(), bitmap.height());
|
||||
|
||||
// Allocate a shared memory buffer to hold the bitmap bits
|
||||
SharedMemory* shared_buf =
|
||||
RenderProcess::AllocSharedMemory(buf_size);
|
||||
if (!shared_buf) {
|
||||
NOTREACHED();
|
||||
return;
|
||||
}
|
||||
if (!shared_buf->Map(buf_size)) {
|
||||
NOTREACHED();
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy the bits into shared memory
|
||||
SkAutoLockPixels bitmap_lock(bitmap);
|
||||
memcpy(shared_buf->memory(), bitmap.getPixels(), buf_size);
|
||||
shared_buf->Unmap();
|
||||
|
||||
// Send the handle over synchronous IPC
|
||||
RenderThread::current()->Send(
|
||||
new ViewHostMsg_ClipboardWriteBitmap(shared_buf->handle(), size));
|
||||
|
||||
// The browser should be done with the bitmap now. It's our job to free
|
||||
// the shared memory.
|
||||
RenderProcess::FreeSharedMemory(shared_buf);
|
||||
}
|
||||
|
||||
void webkit_glue::ClipboardWriteWebSmartPaste() {
|
||||
RenderThread::current()->Send(new ViewHostMsg_ClipboardWriteWebSmartPaste());
|
||||
Clipboard* webkit_glue::ClipboardGetClipboard(){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool webkit_glue::ClipboardIsFormatAvailable(unsigned int format) {
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <vsstyle.h>
|
||||
|
||||
#include "base/gfx/native_theme.h"
|
||||
#include "base/scoped_clipboard_writer.h"
|
||||
#include "base/string_util.h"
|
||||
#include "base/win_util.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
@ -371,10 +372,8 @@ void TextField::Edit::OnCopy() {
|
||||
const std::wstring text(GetSelectedText());
|
||||
|
||||
if (!text.empty()) {
|
||||
ClipboardService* clipboard = g_browser_process->clipboard_service();
|
||||
|
||||
clipboard->Clear();
|
||||
clipboard->WriteText(text);
|
||||
ScopedClipboardWriter scw(g_browser_process->clipboard_service());
|
||||
scw.WriteText(text);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -480,6 +480,10 @@
|
||||
RelativePath="..\..\glue\resource_loader_bridge.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\glue\scoped_clipboard_writer_glue.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\glue\searchable_form_data.cc"
|
||||
>
|
||||
|
29
webkit/glue/scoped_clipboard_writer_glue.h
Normal file
29
webkit/glue/scoped_clipboard_writer_glue.h
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef SCOPED_CLIPBOARD_WRITER_GLUE_H__
|
||||
#define SCOPED_CLIPBOARD_WRITER_GLUE_H__
|
||||
|
||||
#include "base/clipboard.h"
|
||||
#include "base/scoped_clipboard_writer.h"
|
||||
|
||||
class ScopedClipboardWriterGlue : public ScopedClipboardWriter {
|
||||
public:
|
||||
ScopedClipboardWriterGlue(Clipboard* clipboard)
|
||||
: ScopedClipboardWriter(clipboard),
|
||||
shared_buf_(NULL) {
|
||||
}
|
||||
|
||||
~ScopedClipboardWriterGlue();
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void ScopedClipboardWriterGlue::WriteBitmap(const SkBitmap& bitmap);
|
||||
#endif
|
||||
|
||||
private:
|
||||
SharedMemory* shared_buf_;
|
||||
DISALLOW_COPY_AND_ASSIGN(ScopedClipboardWriterGlue);
|
||||
};
|
||||
|
||||
#endif // SCOPED_CLIPBOARD_WRITER_GLUE_H__
|
@ -7,47 +7,33 @@
|
||||
#include <string>
|
||||
|
||||
#include "base/clipboard.h"
|
||||
#include "webkit/glue/scoped_clipboard_writer_glue.h"
|
||||
#include "googleurl/src/gurl.h"
|
||||
|
||||
#include "SkBitmap.h"
|
||||
|
||||
// Clipboard glue
|
||||
// Basically just proxy the calls off to the clipboard
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// The call is being made within the current process.
|
||||
void ScopedClipboardWriterGlue::WriteBitmap(const SkBitmap& bitmap) {
|
||||
SkAutoLockPixels bitmap_lock(bitmap);
|
||||
WriteBitmapFromPixels(bitmap.getPixels(), gfx::Size(bitmap.width(),
|
||||
bitmap.height()));
|
||||
}
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
ScopedClipboardWriterGlue::~ScopedClipboardWriterGlue() {
|
||||
}
|
||||
|
||||
namespace webkit_glue {
|
||||
|
||||
Clipboard clipboard;
|
||||
|
||||
void ClipboardClear() {
|
||||
clipboard.Clear();
|
||||
Clipboard* ClipboardGetClipboard() {
|
||||
return &clipboard;
|
||||
}
|
||||
|
||||
void ClipboardWriteText(const std::wstring& text) {
|
||||
clipboard.WriteText(text);
|
||||
}
|
||||
|
||||
void ClipboardWriteHTML(const std::wstring& html,
|
||||
const GURL& url) {
|
||||
clipboard.WriteHTML(html, url.spec());
|
||||
}
|
||||
|
||||
void ClipboardWriteBookmark(const std::wstring& title,
|
||||
const GURL& url) {
|
||||
clipboard.WriteBookmark(title, url.spec());
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void ClipboardWriteBitmap(const SkBitmap& bitmap) {
|
||||
SkAutoLockPixels bitmap_lock(bitmap);
|
||||
clipboard.WriteBitmap(bitmap.getPixels(),
|
||||
gfx::Size(bitmap.width(), bitmap.height()));
|
||||
}
|
||||
|
||||
void ClipboardWriteWebSmartPaste() {
|
||||
clipboard.WriteWebSmartPaste();
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ClipboardIsFormatAvailable(Clipboard::FormatType format) {
|
||||
return clipboard.IsFormatAvailable(format);
|
||||
}
|
||||
@ -68,4 +54,3 @@ void ClipboardReadHTML(std::wstring* markup, GURL* url) {
|
||||
}
|
||||
|
||||
} // namespace webkit_glue
|
||||
|
||||
|
@ -42,6 +42,7 @@ class Frame;
|
||||
}
|
||||
|
||||
class SkBitmap;
|
||||
class Clipboard;
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
typedef struct CGImage* CGImageRef;
|
||||
@ -194,25 +195,8 @@ HCURSOR LoadCursor(int cursor_id);
|
||||
|
||||
// Glue to access the clipboard.
|
||||
|
||||
// Clear the clipboard. It is usually a good idea to clear the clipboard
|
||||
// before writing content to the clipboard.
|
||||
void ClipboardClear();
|
||||
|
||||
// Adds UNICODE and ASCII text to the clipboard.
|
||||
void ClipboardWriteText(const std::wstring& text);
|
||||
|
||||
// Adds HTML to the clipboard. The url parameter is optional, but especially
|
||||
// useful if the HTML fragment contains relative links
|
||||
void ClipboardWriteHTML(const std::wstring& html, const GURL& url);
|
||||
|
||||
// Adds a bookmark to the clipboard
|
||||
void ClipboardWriteBookmark(const std::wstring& title, const GURL& url);
|
||||
|
||||
// Adds a bitmap to the clipboard
|
||||
void ClipboardWriteBitmap(const SkBitmap& bitmap);
|
||||
|
||||
// Used by WebKit to determine whether WebKit wrote the clipboard last
|
||||
void ClipboardWriteWebSmartPaste();
|
||||
// Get a clipboard that can be used to construct a ScopedClipboardWriterGlue.
|
||||
Clipboard* ClipboardGetClipboard();
|
||||
|
||||
// Tests whether the clipboard contains a certain format
|
||||
bool ClipboardIsFormatAvailable(unsigned int format);
|
||||
|
@ -45,6 +45,7 @@
|
||||
|
||||
#include "base/clipboard_util.h"
|
||||
#include "webkit/glue/glue_util.h"
|
||||
#include "webkit/glue/scoped_clipboard_writer_glue.h"
|
||||
#include "webkit/glue/webkit_glue.h"
|
||||
|
||||
namespace WebCore {
|
||||
@ -70,36 +71,35 @@ Pasteboard::Pasteboard()
|
||||
|
||||
void Pasteboard::clear()
|
||||
{
|
||||
webkit_glue::ClipboardClear();
|
||||
// The ScopedClipboardWriter class takes care of clearing the clipboard's
|
||||
// previous contents.
|
||||
}
|
||||
|
||||
void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame)
|
||||
{
|
||||
clear();
|
||||
ScopedClipboardWriterGlue scw(webkit_glue::ClipboardGetClipboard());
|
||||
|
||||
ExceptionCode ec = 0;
|
||||
webkit_glue::ClipboardWriteHTML(
|
||||
scw.WriteHTML(
|
||||
webkit_glue::StringToStdWString(
|
||||
createMarkup(selectedRange, 0, AnnotateForInterchange)),
|
||||
GURL(webkit_glue::StringToStdWString(
|
||||
selectedRange->startContainer(ec)->document()->url())));
|
||||
selectedRange->startContainer(ec)->document()->url())).spec());
|
||||
|
||||
// Put plain string on the pasteboard. CF_UNICODETEXT covers CF_TEXT as well
|
||||
String str = frame->selectedText();
|
||||
replaceNewlinesWithWindowsStyleNewlines(str);
|
||||
replaceNBSPWithSpace(str);
|
||||
webkit_glue::ClipboardWriteText(webkit_glue::StringToStdWString(str));
|
||||
scw.WriteText(webkit_glue::StringToStdWString(str));
|
||||
|
||||
if (canSmartCopyOrDelete)
|
||||
webkit_glue::ClipboardWriteWebSmartPaste();
|
||||
scw.WriteWebSmartPaste();
|
||||
}
|
||||
|
||||
void Pasteboard::writeURL(const KURL& url, const String& titleStr, Frame* frame)
|
||||
{
|
||||
ASSERT(!url.isEmpty());
|
||||
|
||||
clear();
|
||||
|
||||
String title(titleStr);
|
||||
if (title.isEmpty()) {
|
||||
title = url.lastPathComponent();
|
||||
@ -107,17 +107,19 @@ void Pasteboard::writeURL(const KURL& url, const String& titleStr, Frame* frame)
|
||||
title = url.host();
|
||||
}
|
||||
|
||||
ScopedClipboardWriterGlue scw(webkit_glue::ClipboardGetClipboard());
|
||||
|
||||
// write to clipboard in format com.apple.safari.bookmarkdata to be able to paste into the bookmarks view with appropriate title
|
||||
webkit_glue::ClipboardWriteBookmark(webkit_glue::StringToStdWString(titleStr),
|
||||
webkit_glue::KURLToGURL(url));
|
||||
scw.WriteBookmark(webkit_glue::StringToStdWString(titleStr),
|
||||
webkit_glue::KURLToGURL(url).spec());
|
||||
|
||||
// write to clipboard in format CF_HTML to be able to paste into contenteditable areas as a link
|
||||
std::wstring link(webkit_glue::StringToStdWString(urlToMarkup(url, title)));
|
||||
webkit_glue::ClipboardWriteHTML(link, GURL());
|
||||
scw.WriteHTML(link, GURL().spec());
|
||||
|
||||
// bare-bones CF_UNICODETEXT support
|
||||
std::wstring spec(webkit_glue::StringToStdWString(url));
|
||||
webkit_glue::ClipboardWriteText(spec);
|
||||
scw.WriteText(spec);
|
||||
}
|
||||
|
||||
void Pasteboard::writeImage(Node* node, const KURL& url, const String& title)
|
||||
@ -129,24 +131,23 @@ void Pasteboard::writeImage(Node* node, const KURL& url, const String& title)
|
||||
Image* image = cachedImage->image();
|
||||
ASSERT(image);
|
||||
|
||||
clear();
|
||||
NativeImageSkia* bitmap = image->nativeImageForCurrentFrame();
|
||||
ScopedClipboardWriterGlue scw(webkit_glue::ClipboardGetClipboard());
|
||||
|
||||
if (bitmap)
|
||||
webkit_glue::ClipboardWriteBitmap(*bitmap);
|
||||
scw.WriteBitmap(*bitmap);
|
||||
if (!url.isEmpty()) {
|
||||
webkit_glue::ClipboardWriteBookmark(webkit_glue::StringToStdWString(title),
|
||||
webkit_glue::KURLToGURL(url));
|
||||
// write to clipboard in format com.apple.safari.bookmarkdata to be able to paste into the bookmarks view with appropriate title
|
||||
webkit_glue::ClipboardWriteBookmark(webkit_glue::StringToStdWString(title),
|
||||
webkit_glue::KURLToGURL(url));
|
||||
scw.WriteBookmark(webkit_glue::StringToStdWString(title),
|
||||
webkit_glue::KURLToGURL(url).spec());
|
||||
|
||||
// write to clipboard in format CF_HTML to be able to paste into contenteditable areas as a an image
|
||||
std::wstring markup(webkit_glue::StringToStdWString(urlToImageMarkup(url, title)));
|
||||
webkit_glue::ClipboardWriteHTML(markup, GURL());
|
||||
scw.WriteHTML(markup, GURL().spec());
|
||||
|
||||
// bare-bones CF_UNICODETEXT support
|
||||
std::wstring spec(webkit_glue::StringToStdWString(url.string()));
|
||||
webkit_glue::ClipboardWriteText(spec);
|
||||
scw.WriteText(spec);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user