summaryrefslogtreecommitdiffstats
path: root/base/clipboard_linux.cc
diff options
context:
space:
mode:
authorestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-05 01:34:30 +0000
committerestade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-11-05 01:34:30 +0000
commit3ee3ffd1d79a0c1544f3bfd70c7de7606df9482f (patch)
tree0943a0925f5974478463e5d00886be29109858e6 /base/clipboard_linux.cc
parent38733063b7e1cf0b6e67c0b590773ff4f1aaa18d (diff)
downloadchromium_src-3ee3ffd1d79a0c1544f3bfd70c7de7606df9482f.zip
chromium_src-3ee3ffd1d79a0c1544f3bfd70c7de7606df9482f.tar.gz
chromium_src-3ee3ffd1d79a0c1544f3bfd70c7de7606df9482f.tar.bz2
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
Diffstat (limited to 'base/clipboard_linux.cc')
-rw-r--r--base/clipboard_linux.cc180
1 files changed, 89 insertions, 91 deletions
diff --git a/base/clipboard_linux.cc b/base/clipboard_linux.cc
index 1e4686a..427ec13 100644
--- a/base/clipboard_linux.cc
+++ b/base/clipboard_linux.cc
@@ -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();
+
+ for (ObjectMap::const_iterator iter = objects.begin();
+ iter != objects.end(); ++iter) {
+ DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
+ }
+
+ SetGtkClipboard();
}
-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);
+// 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(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);
+ 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;
-
- SetGtkClipboard();
+ 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;
}
-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);
+void Clipboard::WriteText(const char* text_data, size_t text_len) {
+ char* data = new char[text_len];
+ memcpy(data, text_data, text_len);
- uint8* old_data = InsertOrOverwrite(kMimeHtml, html_data, data_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);
+}
- if (old_data)
- delete[] old_data;
+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);
- SetGtkClipboard();
+ 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()];
-
- 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;
- }
-
- 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;
-}
-
-// Free the pointers in the clipboard_data_ map and reset the map.
-void Clipboard::FreeTargetMap() {
- std::set<uint8*> ptrs;
+// 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);
- 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;
+ if (iter != clipboard_data_->end())
+ delete[] iter->second.first;
- clipboard_data_.clear();
+ (*clipboard_data_)[key] = std::make_pair(data, data_len);
}
-
-// 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;
-}
-