summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-04 21:52:29 +0000
committerestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-04 21:52:29 +0000
commitb08cadb9ab90b41af81b9fd8da65fb52433c8004 (patch)
tree55738edf0c98b596cd6f9a89533e92f5a82c6fff
parent021d688a1e02ae7bd88e54162d5d25e1dae52e7c (diff)
downloadchromium_src-b08cadb9ab90b41af81b9fd8da65fb52433c8004.zip
chromium_src-b08cadb9ab90b41af81b9fd8da65fb52433c8004.tar.gz
chromium_src-b08cadb9ab90b41af81b9fd8da65fb52433c8004.tar.bz2
GTK: implement bookmark manager copy/paste.
- Refactor bookmark util clipboard code to be cross platform. - Add a CBF_DATA format for writing arbitrary data to the clipboard. - Change MenuGtk so that showing a menu only makes the menu items update asynchronously. This way we can show the menu immediately and we won't get in trouble if the delegate's IsCommandEnabled() runs a nested message loop. I did not do any mac-side implementation of the new clipboard stuff. The implementation should be easy when they get around to writing the bookmark manager. Review URL: http://codereview.chromium.org/159815 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@22419 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/clipboard.cc7
-rw-r--r--base/clipboard.h25
-rw-r--r--base/clipboard_linux.cc31
-rw-r--r--base/clipboard_unittest.cc57
-rw-r--r--base/clipboard_win.cc45
-rw-r--r--base/scoped_clipboard_writer.cc17
-rw-r--r--base/scoped_clipboard_writer.h5
-rw-r--r--chrome/browser/bookmarks/bookmark_drag_data.cc67
-rw-r--r--chrome/browser/bookmarks/bookmark_drag_data.h14
-rw-r--r--chrome/browser/bookmarks/bookmark_utils.cc50
-rw-r--r--chrome/browser/gtk/menu_gtk.cc17
-rw-r--r--chrome/browser/gtk/menu_gtk.h6
-rw-r--r--tools/gtk_clipboard_dump/gtk_clipboard_dump.cc5
13 files changed, 268 insertions, 78 deletions
diff --git a/base/clipboard.cc b/base/clipboard.cc
index 57697c5..b0f241e 100644
--- a/base/clipboard.cc
+++ b/base/clipboard.cc
@@ -17,7 +17,7 @@ bool IsBitmapSafe(const Clipboard::ObjectMapParams& params) {
static_cast<size_t>(size->width() * size->height() * 4);
}
-}
+} // namespace
void Clipboard::DispatchObject(ObjectType type, const ObjectMapParams& params) {
switch (type) {
@@ -57,6 +57,11 @@ void Clipboard::DispatchObject(ObjectType type, const ObjectMapParams& params) {
return;
WriteBitmap(&(params[0].front()), &(params[1].front()));
break;
+
+ case CBF_DATA:
+ WriteData(&(params[0].front()), params[0].size(),
+ &(params[1].front()), params[1].size());
+ break;
#endif // defined(OS_WIN) || defined(OS_LINUX)
default:
diff --git a/base/clipboard.h b/base/clipboard.h
index 3b87071..de0f62d 100644
--- a/base/clipboard.h
+++ b/base/clipboard.h
@@ -40,7 +40,8 @@ class Clipboard {
CBF_FILES,
CBF_WEBKIT,
CBF_BITMAP,
- CBF_SMBITMAP // bitmap from shared memory
+ CBF_SMBITMAP, // Bitmap from shared memory.
+ CBF_DATA, // Arbitrary block of bytes.
};
// ObjectMap is a map from ObjectType to associated data.
@@ -67,6 +68,8 @@ class Clipboard {
// size gfx::Size struct
// CBF_SMBITMAP shared_mem shared memory handle
// size gfx::Size struct
+ // CBF_DATA format char array
+ // data byte array
typedef std::vector<char> ObjectMapParam;
typedef std::vector<ObjectMapParam> ObjectMapParams;
typedef std::map<int /* ObjectType */, ObjectMapParams> ObjectMap;
@@ -89,6 +92,10 @@ class Clipboard {
// Tests whether the clipboard contains a certain format
bool IsFormatAvailable(const FormatType& format) const;
+ // As above, but instead of interpreting |format| by some platform-specific
+ // definition, interpret it as a literal MIME type.
+ bool IsFormatAvailableByString(const std::string& format) const;
+
// Reads UNICODE text from the clipboard, if available.
void ReadText(string16* result) const;
@@ -106,6 +113,10 @@ class Clipboard {
void ReadFile(FilePath* file) const;
void ReadFiles(std::vector<FilePath>* files) const;
+ // Reads raw data from the clipboard with the given format type. Stores result
+ // as a byte vector.
+ void ReadData(const std::string& format, std::string* result);
+
// Get format Identifiers for various types.
static FormatType GetUrlFormatType();
static FormatType GetUrlWFormatType();
@@ -132,6 +143,8 @@ class Clipboard {
#endif
private:
+ void DispatchObject(ObjectType type, const ObjectMapParams& params);
+
void WriteText(const char* text_data, size_t text_len);
void WriteHTML(const char* markup_data,
@@ -153,9 +166,13 @@ class Clipboard {
void WriteFiles(const char* file_data, size_t file_len);
- void DispatchObject(ObjectType type, const ObjectMapParams& params);
-
void WriteBitmap(const char* pixel_data, const char* size_data);
+#if defined(OS_WIN) || defined(OS_LINUX)
+ // |format_name| is an ASCII string and should be NULL-terminated.
+ // TODO(estade): port to mac.
+ void WriteData(const char* format_name, size_t format_len,
+ const char* data_data, size_t data_len);
+#endif
#if defined(OS_WIN)
void WriteBitmapFromSharedMemory(const char* bitmap_data,
const char* size_data,
@@ -200,7 +217,7 @@ class Clipboard {
GtkClipboard* clipboard_;
#endif
- DISALLOW_EVIL_CONSTRUCTORS(Clipboard);
+ DISALLOW_COPY_AND_ASSIGN(Clipboard);
};
#endif // BASE_CLIPBOARD_H_
diff --git a/base/clipboard_linux.cc b/base/clipboard_linux.cc
index 552ea79..c259cea 100644
--- a/base/clipboard_linux.cc
+++ b/base/clipboard_linux.cc
@@ -21,7 +21,7 @@ namespace {
const char kMimeBmp[] = "image/bmp";
const char kMimeHtml[] = "text/html";
const char kMimeText[] = "text/plain";
-const char kMimeWebkitSmartPaste[] = "chromium-internal/webkit-paste";
+const char kMimeWebkitSmartPaste[] = "chromium/x-webkit-paste";
std::string GdkAtomToString(const GdkAtom& atom) {
gchar* name = gdk_atom_name(atom);
@@ -193,6 +193,14 @@ void Clipboard::WriteFiles(const char* file_data, size_t file_len) {
NOTIMPLEMENTED();
}
+void Clipboard::WriteData(const char* format_name, size_t format_len,
+ const char* data_data, size_t data_len) {
+ char* data = new char[data_len];
+ memcpy(data, data_data, data_len);
+ std::string format(format_name, format_len);
+ InsertMapping(format.c_str(), data, data_len);
+}
+
// We do not use gtk_clipboard_wait_is_target_available because of
// a bug with the gtk clipboard. It caches the available targets
// and does not always refresh the cache when it is appropriate.
@@ -246,6 +254,10 @@ bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format) const {
return retval;
}
+bool Clipboard::IsFormatAvailableByString(const std::string& format) const {
+ return IsFormatAvailable(format);
+}
+
void Clipboard::ReadText(string16* result) const {
result->clear();
gchar* text = gtk_clipboard_wait_for_text(clipboard_);
@@ -284,9 +296,20 @@ void Clipboard::ReadHTML(string16* markup, std::string* src_url) const {
if (!data)
return;
- UTF8ToUTF16(reinterpret_cast<char*>(data->data),
- strlen(reinterpret_cast<char*>(data->data)),
- markup);
+ UTF8ToUTF16(reinterpret_cast<char*>(data->data), data->length, markup);
+ gtk_selection_data_free(data);
+}
+
+void Clipboard::ReadBookmark(string16* title, std::string* url) const {
+ // TODO(estade): implement this.
+}
+
+void Clipboard::ReadData(const std::string& format, std::string* result) {
+ GtkSelectionData* data =
+ gtk_clipboard_wait_for_contents(clipboard_, StringToGdkAtom(format));
+ if (!data)
+ return;
+ result->assign(reinterpret_cast<char*>(data->data), data->length);
gtk_selection_data_free(data);
}
diff --git a/base/clipboard_unittest.cc b/base/clipboard_unittest.cc
index 808c5e6..dbcaa44 100644
--- a/base/clipboard_unittest.cc
+++ b/base/clipboard_unittest.cc
@@ -8,6 +8,7 @@
#include "base/clipboard.h"
#include "base/gfx/size.h"
#include "base/message_loop.h"
+#include "base/pickle.h"
#include "base/scoped_clipboard_writer.h"
#include "base/string_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -61,8 +62,7 @@ TEST_F(ClipboardTest, TextTest) {
EXPECT_TRUE(clipboard.IsFormatAvailable(
Clipboard::GetPlainTextWFormatType()));
- EXPECT_TRUE(clipboard.IsFormatAvailable(
- Clipboard::GetPlainTextFormatType()));
+ EXPECT_TRUE(clipboard.IsFormatAvailable(Clipboard::GetPlainTextFormatType()));
clipboard.ReadText(&text_result);
EXPECT_EQ(text, text_result);
@@ -81,8 +81,7 @@ TEST_F(ClipboardTest, HTMLTest) {
clipboard_writer.WriteHTML(markup, url);
}
- EXPECT_EQ(true, clipboard.IsFormatAvailable(
- Clipboard::GetHtmlFormatType()));
+ EXPECT_TRUE(clipboard.IsFormatAvailable(Clipboard::GetHtmlFormatType()));
clipboard.ReadHTML(&markup_result, &url_result);
EXPECT_EQ(markup, markup_result);
#if defined(OS_WIN)
@@ -104,8 +103,7 @@ TEST_F(ClipboardTest, TrickyHTMLTest) {
clipboard_writer.WriteHTML(markup, url);
}
- EXPECT_EQ(true, clipboard.IsFormatAvailable(
- Clipboard::GetHtmlFormatType()));
+ EXPECT_TRUE(clipboard.IsFormatAvailable(Clipboard::GetHtmlFormatType()));
clipboard.ReadHTML(&markup_result, &url_result);
EXPECT_EQ(markup, markup_result);
#if defined(OS_WIN)
@@ -128,8 +126,7 @@ TEST_F(ClipboardTest, BookmarkTest) {
clipboard_writer.WriteBookmark(title, url);
}
- EXPECT_EQ(true,
- clipboard.IsFormatAvailable(Clipboard::GetUrlWFormatType()));
+ EXPECT_TRUE(clipboard.IsFormatAvailable(Clipboard::GetUrlWFormatType()));
clipboard.ReadBookmark(&title_result, &url_result);
EXPECT_EQ(title, title_result);
EXPECT_EQ(url, url_result);
@@ -150,11 +147,10 @@ TEST_F(ClipboardTest, MultiFormatTest) {
clipboard_writer.WriteText(text);
}
- EXPECT_EQ(true,
- clipboard.IsFormatAvailable(Clipboard::GetHtmlFormatType()));
- EXPECT_EQ(true, clipboard.IsFormatAvailable(
+ EXPECT_TRUE(clipboard.IsFormatAvailable(Clipboard::GetHtmlFormatType()));
+ EXPECT_TRUE(clipboard.IsFormatAvailable(
Clipboard::GetPlainTextWFormatType()));
- EXPECT_EQ(true, clipboard.IsFormatAvailable(
+ EXPECT_TRUE(clipboard.IsFormatAvailable(
Clipboard::GetPlainTextFormatType()));
clipboard.ReadHTML(&markup_result, &url_result);
EXPECT_EQ(markup, markup_result);
@@ -226,6 +222,32 @@ TEST_F(ClipboardTest, MultipleFilesTest) {
}
#endif // !defined(OS_LINUX)
+#if defined(OS_WIN) || defined(OS_LINUX)
+TEST_F(ClipboardTest, DataTest) {
+ Clipboard clipboard;
+ const char* format = "chromium/x-test-format";
+ std::string payload("test string");
+ Pickle write_pickle;
+ write_pickle.WriteString(payload);
+
+ {
+ ScopedClipboardWriter clipboard_writer(&clipboard);
+ clipboard_writer.WritePickledData(write_pickle, format);
+ }
+
+ ASSERT_TRUE(clipboard.IsFormatAvailableByString(format));
+ std::string output;
+ clipboard.ReadData(format, &output);
+ ASSERT_FALSE(output.empty());
+
+ Pickle read_pickle(output.data(), output.size());
+ void* iter = NULL;
+ std::string unpickled_string;
+ ASSERT_TRUE(read_pickle.ReadString(&iter, &unpickled_string));
+ EXPECT_EQ(payload, unpickled_string);
+}
+#endif
+
#if defined(OS_WIN) // Windows only tests.
TEST_F(ClipboardTest, HyperlinkTest) {
Clipboard clipboard;
@@ -240,10 +262,8 @@ TEST_F(ClipboardTest, HyperlinkTest) {
clipboard_writer.WriteHyperlink(title, url);
}
- EXPECT_EQ(true,
- clipboard.IsFormatAvailable(Clipboard::GetUrlWFormatType()));
- EXPECT_EQ(true,
- clipboard.IsFormatAvailable(Clipboard::GetHtmlFormatType()));
+ EXPECT_TRUE(clipboard.IsFormatAvailable(Clipboard::GetUrlWFormatType()));
+ EXPECT_TRUE(clipboard.IsFormatAvailable(Clipboard::GetHtmlFormatType()));
clipboard.ReadBookmark(&title_result, &url_result);
EXPECT_EQ(title, title_result);
EXPECT_EQ(url, url_result);
@@ -259,7 +279,7 @@ TEST_F(ClipboardTest, WebSmartPasteTest) {
clipboard_writer.WriteWebSmartPaste();
}
- EXPECT_EQ(true, clipboard.IsFormatAvailable(
+ EXPECT_TRUE(clipboard.IsFormatAvailable(
Clipboard::GetWebKitSmartPasteFormatType()));
}
@@ -277,7 +297,6 @@ TEST_F(ClipboardTest, BitmapTest) {
clipboard_writer.WriteBitmapFromPixels(fake_bitmap, gfx::Size(3, 4));
}
- EXPECT_EQ(true, clipboard.IsFormatAvailable(
- Clipboard::GetBitmapFormatType()));
+ EXPECT_TRUE(clipboard.IsFormatAvailable(Clipboard::GetBitmapFormatType()));
}
#endif // defined(OS_WIN)
diff --git a/base/clipboard_win.cc b/base/clipboard_win.cc
index 371e8f5..bd88efa 100644
--- a/base/clipboard_win.cc
+++ b/base/clipboard_win.cc
@@ -373,6 +373,22 @@ void Clipboard::WriteFiles(const char* file_data, size_t file_len) {
WriteToClipboard(CF_HDROP, hdata);
}
+void Clipboard::WriteData(const char* format_name, size_t format_len,
+ const char* data_data, size_t data_len) {
+ std::string format(format_name, format_len);
+ CLIPFORMAT clip_format =
+ ::RegisterClipboardFormat(ASCIIToWide(format).c_str());
+
+ HGLOBAL hdata = ::GlobalAlloc(GMEM_MOVEABLE, data_len);
+ if (!hdata)
+ return;
+
+ char* data = static_cast<char*>(::GlobalLock(hdata));
+ memcpy(data, data_data, data_len);
+ ::GlobalUnlock(data);
+ WriteToClipboard(clip_format, hdata);
+}
+
void Clipboard::WriteToClipboard(unsigned int format, HANDLE handle) {
DCHECK(clipboard_owner_);
if (handle && !::SetClipboardData(format, handle)) {
@@ -385,6 +401,13 @@ bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format) const {
return ::IsClipboardFormatAvailable(StringToInt(format)) != FALSE;
}
+bool Clipboard::IsFormatAvailableByString(
+ const std::string& ascii_format) const {
+ std::wstring wide_format = ASCIIToWide(ascii_format);
+ CLIPFORMAT format = ::RegisterClipboardFormat(wide_format.c_str());
+ return ::IsClipboardFormatAvailable(format) != FALSE;
+}
+
void Clipboard::ReadText(string16* result) const {
if (!result) {
NOTREACHED();
@@ -521,6 +544,28 @@ void Clipboard::ReadFiles(std::vector<FilePath>* files) const {
}
}
+void Clipboard::ReadData(const std::string& format, std::string* result) {
+ if (!result) {
+ NOTREACHED();
+ return;
+ }
+
+ CLIPFORMAT clip_format =
+ ::RegisterClipboardFormat(ASCIIToWide(format).c_str());
+
+ ScopedClipboard clipboard;
+ if (!clipboard.Acquire(GetClipboardWindow()))
+ return;
+
+ HANDLE data = ::GetClipboardData(clip_format);
+ if (!data)
+ return;
+
+ result->assign(static_cast<const char*>(::GlobalLock(data)),
+ ::GlobalSize(data));
+ ::GlobalUnlock(data);
+}
+
// static
void Clipboard::ParseBookmarkClipboardFormat(const string16& bookmark,
string16* title,
diff --git a/base/scoped_clipboard_writer.cc b/base/scoped_clipboard_writer.cc
index f413061..1e9e846 100644
--- a/base/scoped_clipboard_writer.cc
+++ b/base/scoped_clipboard_writer.cc
@@ -6,9 +6,11 @@
// purpose can be found in base/scoped_clipboard_writer.h. Documentation on the
// format of the parameters for each clipboard target can be found in
// base/clipboard.h.
+
#include "base/scoped_clipboard_writer.h"
#include "base/gfx/size.h"
+#include "base/pickle.h"
#include "base/string_util.h"
ScopedClipboardWriter::ScopedClipboardWriter(Clipboard* clipboard)
@@ -139,3 +141,18 @@ void ScopedClipboardWriter::WriteBitmapFromPixels(const void* pixels,
parameters.push_back(size_parameter);
objects_[Clipboard::CBF_BITMAP] = parameters;
}
+
+void ScopedClipboardWriter::WritePickledData(const Pickle& pickle,
+ Clipboard::FormatType format) {
+ Clipboard::ObjectMapParam format_parameter(format.begin(), format.end());
+ Clipboard::ObjectMapParam data_parameter;
+
+ data_parameter.resize(pickle.size());
+ memcpy(const_cast<char*>(&data_parameter.front()),
+ pickle.data(), pickle.size());
+
+ Clipboard::ObjectMapParams parameters;
+ parameters.push_back(format_parameter);
+ parameters.push_back(data_parameter);
+ objects_[Clipboard::CBF_DATA] = parameters;
+}
diff --git a/base/scoped_clipboard_writer.h b/base/scoped_clipboard_writer.h
index 03ac892..9d1760a 100644
--- a/base/scoped_clipboard_writer.h
+++ b/base/scoped_clipboard_writer.h
@@ -17,6 +17,8 @@
#include "base/file_path.h"
#include "base/string16.h"
+class Pickle;
+
// 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
@@ -55,6 +57,9 @@ class ScopedClipboardWriter {
// Pixel format is assumed to be 32-bit BI_RGB.
void WriteBitmapFromPixels(const void* pixels, const gfx::Size& size);
+ // Adds arbitrary data to clipboard.
+ void WritePickledData(const Pickle& pickle, Clipboard::FormatType format);
+
protected:
// We accumulate the data passed to the various targets in the |objects_|
// vector, and pass it to Clipboard::WriteObjects() during object destruction.
diff --git a/chrome/browser/bookmarks/bookmark_drag_data.cc b/chrome/browser/bookmarks/bookmark_drag_data.cc
index bf3ae05..0ed2273 100644
--- a/chrome/browser/bookmarks/bookmark_drag_data.cc
+++ b/chrome/browser/bookmarks/bookmark_drag_data.cc
@@ -4,25 +4,33 @@
#include "chrome/browser/bookmarks/bookmark_drag_data.h"
-// TODO(port): Port this file.
-#if defined(TOOLKIT_VIEWS)
-#include "app/os_exchange_data.h"
-#else
-#include "chrome/common/temp_scaffolding_stubs.h"
-#endif
#include "base/basictypes.h"
#include "base/pickle.h"
+#include "base/scoped_clipboard_writer.h"
#include "base/string_util.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/profile.h"
#include "chrome/common/url_constants.h"
+#include "chrome/browser/browser_process.h"
+
+// TODO(port): Port this file.
+#if defined(TOOLKIT_VIEWS)
+#include "app/os_exchange_data.h"
+#else
+#include "chrome/common/temp_scaffolding_stubs.h"
+#endif
+
+const char* BookmarkDragData::kClipboardFormatString =
+ "chromium/x-bookmark-entries";
#if defined(OS_WIN)
static CLIPFORMAT clipboard_format = 0;
static void RegisterFormat() {
if (clipboard_format == 0) {
- clipboard_format = RegisterClipboardFormat(L"chrome/x-bookmark-entries");
+ clipboard_format =
+ ::RegisterClipboardFormat(ASCIIToWide(
+ BookmarkDragData::kClipboardFormatString).c_str());
DCHECK(clipboard_format);
}
}
@@ -86,6 +94,51 @@ BookmarkDragData::BookmarkDragData(
elements.push_back(Element(nodes[i]));
}
+#if !defined(OS_MACOSX)
+void BookmarkDragData::WriteToClipboard(Profile* profile) const {
+ ScopedClipboardWriter scw(g_browser_process->clipboard());
+
+ // If there is only one element and it is a URL, write the URL to the
+ // clipboard.
+ if (elements.size() == 1 && elements[0].is_url) {
+ scw.WriteBookmark(WideToUTF16Hack(elements[0].title),
+ elements[0].url.spec());
+ }
+
+ Pickle pickle;
+ WriteToPickle(profile, &pickle);
+ scw.WritePickledData(pickle, kClipboardFormatString);
+}
+
+bool BookmarkDragData::ReadFromClipboard() {
+ std::string data;
+ Clipboard* clipboard = g_browser_process->clipboard();
+ clipboard->ReadData(kClipboardFormatString, &data);
+
+ if (!data.empty()) {
+ Pickle pickle(data.data(), data.size());
+ if (ReadFromPickle(&pickle))
+ return true;
+ }
+
+ string16 title;
+ std::string url;
+ clipboard->ReadBookmark(&title, &url);
+ if (!url.empty()) {
+ Element element;
+ element.is_url = true;
+ element.url = GURL(url);
+ element.title = UTF16ToWideHack(title);
+
+ elements.clear();
+ elements.push_back(element);
+ return true;
+ }
+
+ return false;
+}
+#endif // !defined(OS_MACOSX)
+
#if defined(OS_WIN)
void BookmarkDragData::Write(Profile* profile, OSExchangeData* data) const {
RegisterFormat();
diff --git a/chrome/browser/bookmarks/bookmark_drag_data.h b/chrome/browser/bookmarks/bookmark_drag_data.h
index 9af3c20..815e8e1d 100644
--- a/chrome/browser/bookmarks/bookmark_drag_data.h
+++ b/chrome/browser/bookmarks/bookmark_drag_data.h
@@ -71,6 +71,17 @@ struct BookmarkDragData {
explicit BookmarkDragData(const BookmarkNode* node);
explicit BookmarkDragData(const std::vector<const BookmarkNode*>& nodes);
+ // TODO(estade): Port to mac. It should be as simple as removing this ifdef
+ // after the relevant Clipboard functions are implemetned.
+#if !defined(OS_MACOSX)
+ // Writes elements to the clipboard.
+ void WriteToClipboard(Profile* profile) const;
+
+ // Reads bookmarks from the clipboard. Prefers data written via
+ // WriteToClipboard but will also attempt to read a plain bookmark.
+ bool ReadFromClipboard();
+#endif
+
#if defined(TOOLKIT_VIEWS)
// Writes elements to data. If there is only one element and it is a URL
// the URL and title are written to the clipboard in a format other apps can
@@ -114,6 +125,9 @@ struct BookmarkDragData {
// The actual elements written to the clipboard.
std::vector<Element> elements;
+ // The MIME type for the clipboard format for BookmarkDragData.
+ static const char* kClipboardFormatString;
+
private:
// Path of the profile we originated from.
#if defined(WCHAR_T_IS_UTF16)
diff --git a/chrome/browser/bookmarks/bookmark_utils.cc b/chrome/browser/bookmarks/bookmark_utils.cc
index 7371497..51250c3 100644
--- a/chrome/browser/bookmarks/bookmark_utils.cc
+++ b/chrome/browser/bookmarks/bookmark_utils.cc
@@ -6,20 +6,16 @@
#include "app/drag_drop_types.h"
#include "app/l10n_util.h"
-// TODO(port): Port these files.
-#if defined(OS_WIN)
-#include "app/os_exchange_data.h"
-#else
-#include "chrome/common/temp_scaffolding_stubs.h"
-#endif
#include "app/tree_node_iterator.h"
#include "base/basictypes.h"
+#include "base/clipboard.h"
#include "base/string_util.h"
#include "base/time.h"
#include "chrome/browser/bookmarks/bookmark_drag_data.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/history/query_parser.h"
#include "chrome/browser/profile.h"
@@ -355,53 +351,39 @@ void OpenAll(gfx::NativeView parent,
void CopyToClipboard(BookmarkModel* model,
const std::vector<const BookmarkNode*>& nodes,
bool remove_nodes) {
+#if defined(OS_WIN) || defined(OS_LINUX)
if (nodes.empty())
return;
-#if defined(OS_WIN)
- OSExchangeData* data = new OSExchangeData();
- BookmarkDragData(nodes).Write(NULL, data);
- OleSetClipboard(data);
- // OLE takes ownership of OSExchangeData.
-#else
- // TODO(port): Clipboard integration. Don't we have clipboard
- // implemented somewhere else?
-#endif
+ BookmarkDragData(nodes).WriteToClipboard(NULL);
- // The following works cross-platform but I'm disabling it for now so that
- // users who Cut a bookmark or folder won't lose it without being able to
- // paste it.
-#if defined(OS_WIN)
if (remove_nodes) {
for (size_t i = 0; i < nodes.size(); ++i) {
model->Remove(nodes[i]->GetParent(),
nodes[i]->GetParent()->IndexOfChild(nodes[i]));
}
}
+#else
+ // Not implemented on mac yet.
#endif
}
void PasteFromClipboard(BookmarkModel* model,
const BookmarkNode* parent,
int index) {
+#if defined(OS_WIN) || defined(OS_LINUX)
if (!parent)
return;
-#if defined(OS_WIN)
- IDataObject* data;
- if (OleGetClipboard(&data) != S_OK)
- return;
-
- OSExchangeData data_wrapper(data);
BookmarkDragData bookmark_data;
- if (!bookmark_data.Read(data_wrapper))
+ if (!bookmark_data.ReadFromClipboard())
return;
if (index == -1)
index = parent->GetChildCount();
bookmark_utils::CloneDragData(model, bookmark_data.elements, parent, index);
#else
- // TODO(port): Clipboard integration.
+ // Not implemented on mac yet.
#endif
}
@@ -409,18 +391,8 @@ bool CanPasteFromClipboard(const BookmarkNode* node) {
if (!node)
return false;
-#if defined(OS_WIN)
- IDataObject* data;
- if (OleGetClipboard(&data) != S_OK)
- return false;
-
- OSExchangeData data_wrapper(data);
- BookmarkDragData bookmark_data;
- return bookmark_data.Read(data_wrapper);
-#else
- // TODO(port): Clipboard integration.
- return false;
-#endif
+ return g_browser_process->clipboard()->IsFormatAvailable(
+ BookmarkDragData::kClipboardFormatString);
}
std::string GetNameForURL(const GURL& url) {
diff --git a/chrome/browser/gtk/menu_gtk.cc b/chrome/browser/gtk/menu_gtk.cc
index 492bc97..73a3296 100644
--- a/chrome/browser/gtk/menu_gtk.cc
+++ b/chrome/browser/gtk/menu_gtk.cc
@@ -7,6 +7,7 @@
#include "app/l10n_util.h"
#include "base/gfx/gtk_util.h"
#include "base/logging.h"
+#include "base/message_loop.h"
#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "chrome/browser/gtk/standard_menus.h"
@@ -22,7 +23,8 @@ MenuGtk::MenuGtk(MenuGtk::Delegate* delegate,
GtkAccelGroup* accel_group)
: delegate_(delegate),
dummy_accel_group_(gtk_accel_group_new()),
- menu_(gtk_menu_new()) {
+ menu_(gtk_menu_new()),
+ factory_(this) {
ConnectSignalHandlers();
BuildMenuIn(menu_.get(), menu_data, accel_group);
}
@@ -30,7 +32,8 @@ MenuGtk::MenuGtk(MenuGtk::Delegate* delegate,
MenuGtk::MenuGtk(MenuGtk::Delegate* delegate, bool load)
: delegate_(delegate),
dummy_accel_group_(NULL),
- menu_(gtk_menu_new()) {
+ menu_(gtk_menu_new()),
+ factory_(this) {
ConnectSignalHandlers();
if (load)
BuildMenuFromDelegate();
@@ -43,6 +46,8 @@ MenuGtk::~MenuGtk() {
}
void MenuGtk::ConnectSignalHandlers() {
+ // We connect afterwards because OnMenuShow calls SetMenuItemInfo, which may
+ // take a long time or even start a nested message loop.
g_signal_connect(menu_.get(), "show", G_CALLBACK(OnMenuShow), this);
g_signal_connect(menu_.get(), "hide", G_CALLBACK(OnMenuHidden), this);
}
@@ -293,10 +298,14 @@ void MenuGtk::MenuPositionFunc(GtkMenu* menu,
*push_in = FALSE;
}
+void MenuGtk::UpdateMenu() {
+ gtk_container_foreach(GTK_CONTAINER(menu_.get()), SetMenuItemInfo, this);
+}
+
// static
void MenuGtk::OnMenuShow(GtkWidget* widget, MenuGtk* menu) {
- gtk_container_foreach(GTK_CONTAINER(menu->menu_.get()),
- SetMenuItemInfo, menu);
+ MessageLoop::current()->PostTask(FROM_HERE,
+ menu->factory_.NewRunnableMethod(&MenuGtk::UpdateMenu));
}
// static
diff --git a/chrome/browser/gtk/menu_gtk.h b/chrome/browser/gtk/menu_gtk.h
index b06c77c..2d47f67 100644
--- a/chrome/browser/gtk/menu_gtk.h
+++ b/chrome/browser/gtk/menu_gtk.h
@@ -9,6 +9,7 @@
#include <string>
+#include "base/task.h"
#include "chrome/common/owned_widget_gtk.h"
class SkBitmap;
@@ -114,6 +115,9 @@ class MenuGtk {
// recursive and does not support sub-menus.
void BuildMenuFromDelegate();
+ // Contains implementation for OnMenuShow.
+ void UpdateMenu();
+
// Callback for when a menu item is clicked.
static void OnMenuItemActivated(GtkMenuItem* menuitem, MenuGtk* menu);
@@ -142,6 +146,8 @@ class MenuGtk {
// menu items from getting activated when we are setting up the
// menu.
static bool block_activation_;
+
+ ScopedRunnableMethodFactory<MenuGtk> factory_;
};
#endif // CHROME_BROWSER_GTK_MENU_GTK_H_
diff --git a/tools/gtk_clipboard_dump/gtk_clipboard_dump.cc b/tools/gtk_clipboard_dump/gtk_clipboard_dump.cc
index a064792..c96ee00 100644
--- a/tools/gtk_clipboard_dump/gtk_clipboard_dump.cc
+++ b/tools/gtk_clipboard_dump/gtk_clipboard_dump.cc
@@ -19,6 +19,11 @@ void PrintClipboardContents(GtkClipboard* clip) {
GtkSelectionData* target_data =
gtk_clipboard_wait_for_contents(clip,
gdk_atom_intern("TARGETS", false));
+ if (!target_data) {
+ printf("failed to get the contents!\n");
+ return;
+ }
+
gtk_selection_data_get_targets(target_data, &targets, &num_targets);
printf("%d available targets:\n---------------\n", num_targets);