diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-04 21:52:29 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-04 21:52:29 +0000 |
commit | b08cadb9ab90b41af81b9fd8da65fb52433c8004 (patch) | |
tree | 55738edf0c98b596cd6f9a89533e92f5a82c6fff | |
parent | 021d688a1e02ae7bd88e54162d5d25e1dae52e7c (diff) | |
download | chromium_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.cc | 7 | ||||
-rw-r--r-- | base/clipboard.h | 25 | ||||
-rw-r--r-- | base/clipboard_linux.cc | 31 | ||||
-rw-r--r-- | base/clipboard_unittest.cc | 57 | ||||
-rw-r--r-- | base/clipboard_win.cc | 45 | ||||
-rw-r--r-- | base/scoped_clipboard_writer.cc | 17 | ||||
-rw-r--r-- | base/scoped_clipboard_writer.h | 5 | ||||
-rw-r--r-- | chrome/browser/bookmarks/bookmark_drag_data.cc | 67 | ||||
-rw-r--r-- | chrome/browser/bookmarks/bookmark_drag_data.h | 14 | ||||
-rw-r--r-- | chrome/browser/bookmarks/bookmark_utils.cc | 50 | ||||
-rw-r--r-- | chrome/browser/gtk/menu_gtk.cc | 17 | ||||
-rw-r--r-- | chrome/browser/gtk/menu_gtk.h | 6 | ||||
-rw-r--r-- | tools/gtk_clipboard_dump/gtk_clipboard_dump.cc | 5 |
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); |